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

  1. /* *** Listing 20.3 ***
  2.  *
  3.  * Draws an ellipse of the specified X and Y axis radii and color,
  4.  * using a fast integer-only & square-root-free approach, and
  5.  * generating the arc for one octant into a buffer, drawing four
  6.  * symmetries from that buffer, then doing the same for the other
  7.  * axis. Uses assembly language for inner loops of octant generation
  8.  * & drawing.
  9.  * VGA or EGA.
  10.  * Compiled with Borland C++ 4.02.  Link with L20-2.C and L20-4.ASM.
  11.  * Checked by Jim Mischel 11/30/94.
  12.  * VGA or EGA.
  13.  */
  14. #define ISVGA  0              /* set to 1 to use VGA write mode 3*/
  15.                               /* keep synchronized with Listing 4 */
  16. #include <dos.h>
  17.  
  18. /* Handle differences between Turbo C & MSC. Note that Turbo C accepts
  19.    outp as a synonym for outportb, but not outpw for outport */
  20. #ifdef __TURBOC__
  21. #define outpw  outport
  22. #endif
  23.  
  24. #define SCREEN_WIDTH_IN_BYTES 80    /* # of bytes across one scan
  25.                                        line in mode 12h */
  26. #define SCREEN_SEGMENT        0xA000 /* mode 12h display memory seg */
  27. #define GC_INDEX              0x3CE /* Graphics Controller port */
  28. #define SET_RESET_INDEX       0     /* Set/Reset reg index in GC */
  29. #define SET_RESET_ENABLE_INDEX 1    /* Set/Reset Enable reg index
  30.                                        in GC */
  31. #define GC_MODE_INDEX         5  /* Graphics Mode reg index in GC */
  32. #define COLOR_DONT_CARE       7  /* Color Don't Care reg index in GC */
  33. #define BIT_MASK_INDEX        8     /* Bit Mask reg index in GC */
  34.  
  35. unsigned char PixList[SCREEN_WIDTH_IN_BYTES*8/2];
  36.                                     /* maximum major axis length is
  37.                                        1/2 screen width, because we're
  38.                                        assuming no clipping is needed */
  39.  
  40. /* Draws an ellipse of X axis radius A and Y axis radius B in
  41.  * color Color centered at screen coordinate (X,Y). Radii must
  42.  * both be non-zero */
  43. void DrawEllipse(int X, int Y, int A, int B, int Color) {
  44.    int Length;
  45.    long Threshold;
  46.    long ASquared = (long) A * A;
  47.    long BSquared = (long) B * B;
  48.    long XAdjust, YAdjust;
  49.    unsigned char *PixListPtr, OriginalGCMode;
  50.  
  51.    /* Set drawing color via set/reset */
  52.    outpw(GC_INDEX, (0x0F << 8) | SET_RESET_ENABLE_INDEX);
  53.                                  /* enable set/reset for all planes */
  54.    outpw(GC_INDEX, (Color << 8) | SET_RESET_INDEX);
  55.                                  /* set set/reset (drawing) color */
  56. #if ISVGA
  57.    /* Remember original read/write mode & select
  58.       read mode 1/write mode 3, with Color Don't Care
  59.       set to ignore all planes and therefore always return 0xFF */
  60.    outp(GC_INDEX, GC_MODE_INDEX);
  61.    OriginalGCMode = inp(GC_INDEX + 1);
  62.    outp(GC_INDEX+1, OriginalGCMode | 0x0B);
  63.    outpw(GC_INDEX, (0x00 << 8) | COLOR_DONT_CARE);
  64.    outpw(GC_INDEX, (0xFF << 8) | BIT_MASK_INDEX);
  65. #else
  66.    outp(GC_INDEX, BIT_MASK_INDEX); /* leave the GC Index reg pointing
  67.                                        to the Bit Mask reg */
  68. #endif
  69.  
  70.    /* Draw the four symmetric arcs for which X advances faster (that is,
  71.       for which X is the major axis) */
  72.    /* Generate the draw list for 1 octant */
  73.    Length = GenerateEOctant(PixList, (long) ASquared * 2 * B,
  74.       (long) ASquared / 4 - ASquared * B, ASquared, BSquared);
  75.  
  76.    /* Now draw each of 4 symmetries of the octant in turn, the
  77.       octants for which X is the major axis. Adjust every other arc
  78.       so that there's no overlap */
  79.    DrawHOctant(X,Y-B,Length,SCREEN_WIDTH_IN_BYTES,0,PixList);
  80.    DrawHOctant(X+1,Y-B+(*PixList),Length-1,SCREEN_WIDTH_IN_BYTES,1,
  81.       PixList+1);
  82.    DrawHOctant(X,Y+B,Length,-SCREEN_WIDTH_IN_BYTES,0,PixList);
  83.    DrawHOctant(X+1,Y+B-(*PixList),Length-1,-SCREEN_WIDTH_IN_BYTES,1,
  84.       PixList+1);
  85.  
  86.    /* Draw the four symmetric arcs for which Y advances faster (that is,
  87.       for which Y is the major axis) */
  88.    /* Generate the draw list for 1 octant */
  89.    Length = GenerateEOctant(PixList, (long) BSquared * 2 * A,
  90.       (long) BSquared / 4 - BSquared * A, BSquared, ASquared);
  91.  
  92.    /* Now draw each of 4 symmetries of the octant in turn, the
  93.       octants for which X is the major axis. Adjust every other arc
  94.       so that there's no overlap */
  95.    DrawVOctant(X-A,Y,Length,-SCREEN_WIDTH_IN_BYTES,1,PixList);
  96.    DrawVOctant(X-A+(*PixList),Y+1,Length-1,SCREEN_WIDTH_IN_BYTES,1,
  97.       PixList+1);
  98.    DrawVOctant(X+A,Y,Length,-SCREEN_WIDTH_IN_BYTES,0,PixList);
  99.    DrawVOctant(X+A-(*PixList),Y+1,Length-1,SCREEN_WIDTH_IN_BYTES,0,
  100.       PixList+1);
  101.  
  102. #if ISVGA
  103.    /* Restore original write mode */
  104.    outpw(GC_INDEX, (OriginalGCMode << 8) | GC_MODE_INDEX);
  105.    /* Restore normal Color Don't Care setting */
  106.    outpw(GC_INDEX, (0x0F << 8) | COLOR_DONT_CARE);
  107. #else
  108.    /* Reset the Bit Mask register to normal */
  109.    outp(GC_INDEX + 1, 0xFF);
  110. #endif
  111.    /* Turn off set/reset enable */
  112.    outpw(GC_INDEX, (0x00 << 8) | SET_RESET_ENABLE_INDEX);
  113. }
  114.