home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapterc / lc-3.c < prev    next >
C/C++ Source or Header  |  1997-06-18  |  5KB  |  103 lines

  1. /* *** Listing 18.3 ***
  2.  *
  3.  * Draws a circle of the specified radius and color, using a fast
  4.  * integer-only & square-root-free approach, and generating the
  5.  * arc for one octant into a buffer, then drawing all 8 symmetries
  6.  * from that buffer. Uses assembly language for inner loops of octant
  7.  * generation & drawing.
  8.  * Will work on VGA or EGA, but will draw what appears to be an
  9.  * ellipse in non-square-pixel modes.
  10.  * Compiled with Borland C++ 4.02.  Link with L18-2.C and L18-4.ASM.
  11.  * Checked by Jim Mischel 11/30/94.
  12.  */
  13. #define ISVGA  0              /* set to 1 to use VGA write mode 3*/
  14.                               /* keep synchronized with Listing 4 */
  15. #include <dos.h>
  16.  
  17. /* Handle differences between Turbo C & MSC. Note that Turbo C accepts
  18.    outp as a synonym for outportb, but not outpw for outport */
  19. #ifdef __TURBOC__
  20. #define outpw  outport
  21. #endif
  22.  
  23. #define SCREEN_WIDTH_IN_BYTES 80    /* # of bytes across one scan
  24.                                        line in mode 12h */
  25. #define SCREEN_SEGMENT        0xA000 /* mode 12h display memory seg */
  26. #define GC_INDEX              0x3CE /* Graphics Controller port */
  27. #define SET_RESET_INDEX       0  /* Set/Reset reg index in GC */
  28. #define SET_RESET_ENABLE_INDEX 1 /* Set/Reset Enable reg index in GC */
  29. #define GC_MODE_INDEX         5  /* Graphics Mode reg index in GC */
  30. #define COLOR_DONT_CARE       7  /* Color Don't Care reg index in GC */
  31. #define BIT_MASK_INDEX        8  /* Bit Mask reg index in GC */
  32.  
  33. unsigned char PixList[SCREEN_WIDTH_IN_BYTES*8/2];
  34.                                     /* maximum major axis length is
  35.                                        1/2 screen width, because we're
  36.                                        assuming no clipping is needed */
  37. /* Draws a circle of radius Radius in color Color centered at
  38.  * screen coordinate (X,Y) */
  39. void DrawCircle(int X, int Y, int Radius, int Color) {
  40.    int MajorAxis, MinorAxis;
  41.    unsigned long RadiusSqMinusMajorAxisSq, MinorAxisSquaredThreshold;
  42.    unsigned char *PixListPtr, OriginalGCMode;
  43.  
  44.    /* Set drawing color via set/reset */
  45.    outpw(GC_INDEX, (0x0F << 8) | SET_RESET_ENABLE_INDEX);
  46.                                  /* enable set/reset for all planes */
  47.    outpw(GC_INDEX, (Color << 8) | SET_RESET_INDEX);
  48.                                  /* set set/reset (drawing) color */
  49. #if ISVGA
  50.    /* Remember original read/write mode & select
  51.       read mode 1/write mode 3, with Color Don't Care
  52.       set to ignore all planes and therefore always return 0xFF */
  53.    outp(GC_INDEX, GC_MODE_INDEX);
  54.    OriginalGCMode = inp(GC_INDEX + 1);
  55.    outp(GC_INDEX+1, OriginalGCMode | 0x0B);
  56.    outpw(GC_INDEX, (0x00 << 8) | COLOR_DONT_CARE);
  57.    outpw(GC_INDEX, (0xFF << 8) | BIT_MASK_INDEX);
  58. #else
  59.    outp(GC_INDEX, BIT_MASK_INDEX); /* leave the GC Index reg pointing
  60.                                        to the Bit Mask reg */
  61. #endif
  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.    /* Set initial Radius**2 - MajorAxis**2 (MajorAxis is initially 0) */
  68.    RadiusSqMinusMajorAxisSq = (unsigned long) Radius * Radius;
  69.    /* Set threshold for minor axis movement at (MinorAxis - 0.5)**2 */
  70.    MinorAxisSquaredThreshold = (unsigned long) MinorAxis * MinorAxis -
  71.       MinorAxis;
  72.  
  73.    /* Calculate all points along an arc of 1/8th of the circle.
  74.       Results are placed in PixList */
  75.    MajorAxis = GenerateOctant(PixList, MajorAxis, MinorAxis,
  76.       RadiusSqMinusMajorAxisSq, MinorAxisSquaredThreshold);
  77.  
  78.    /* Now draw each of the 8 symmetries of the octant in turn */
  79.    /* Draw the octants for which Y is the major axis */
  80.    DrawVOctant(X-Radius,Y,MajorAxis,-SCREEN_WIDTH_IN_BYTES,1,PixList);
  81.    DrawVOctant(X-Radius,Y,MajorAxis,SCREEN_WIDTH_IN_BYTES,1,PixList);
  82.    DrawVOctant(X+Radius,Y,MajorAxis,-SCREEN_WIDTH_IN_BYTES,0,PixList);
  83.    DrawVOctant(X+Radius,Y,MajorAxis,SCREEN_WIDTH_IN_BYTES,0,PixList);
  84.  
  85.    /* Draw the octants for which X is the major axis */
  86.    DrawHOctant(X,Y-Radius,MajorAxis,SCREEN_WIDTH_IN_BYTES,0,PixList);
  87.    DrawHOctant(X,Y-Radius,MajorAxis,SCREEN_WIDTH_IN_BYTES,1,PixList);
  88.    DrawHOctant(X,Y+Radius,MajorAxis,-SCREEN_WIDTH_IN_BYTES,0, PixList);
  89.    DrawHOctant(X,Y+Radius,MajorAxis,-SCREEN_WIDTH_IN_BYTES,1, PixList);
  90.  
  91. #if ISVGA
  92.    /* Restore original write mode */
  93.    outpw(GC_INDEX, (OriginalGCMode << 8) | GC_MODE_INDEX);
  94.    /* Restore normal Color Don't Care setting */
  95.    outpw(GC_INDEX, (0x0F << 8) | COLOR_DONT_CARE);
  96. #else
  97.    /* Reset the Bit Mask register to normal */
  98.    outp(GC_INDEX + 1, 0xFF);
  99. #endif
  100.    /* Turn off set/reset enable */
  101.    outpw(GC_INDEX, (0x00 << 8) | SET_RESET_ENABLE_INDEX);
  102. }
  103.