home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Programming Black Book (Special Edition)
/
BlackBook.bin
/
disk1
/
source
/
chapterc
/
lc-3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-18
|
5KB
|
103 lines
/* *** Listing 18.3 ***
*
* Draws a circle of the specified radius and color, using a fast
* integer-only & square-root-free approach, and generating the
* arc for one octant into a buffer, then drawing all 8 symmetries
* from that buffer. Uses assembly language for inner loops of octant
* generation & drawing.
* Will work on VGA or EGA, but will draw what appears to be an
* ellipse in non-square-pixel modes.
* Compiled with Borland C++ 4.02. Link with L18-2.C and L18-4.ASM.
* Checked by Jim Mischel 11/30/94.
*/
#define ISVGA 0 /* set to 1 to use VGA write mode 3*/
/* keep synchronized with Listing 4 */
#include <dos.h>
/* Handle differences between Turbo C & MSC. Note that Turbo C accepts
outp as a synonym for outportb, but not outpw for outport */
#ifdef __TURBOC__
#define outpw outport
#endif
#define SCREEN_WIDTH_IN_BYTES 80 /* # of bytes across one scan
line in mode 12h */
#define SCREEN_SEGMENT 0xA000 /* mode 12h display memory seg */
#define GC_INDEX 0x3CE /* Graphics Controller port */
#define SET_RESET_INDEX 0 /* Set/Reset reg index in GC */
#define SET_RESET_ENABLE_INDEX 1 /* Set/Reset Enable reg index in GC */
#define GC_MODE_INDEX 5 /* Graphics Mode reg index in GC */
#define COLOR_DONT_CARE 7 /* Color Don't Care reg index in GC */
#define BIT_MASK_INDEX 8 /* Bit Mask reg index in GC */
unsigned char PixList[SCREEN_WIDTH_IN_BYTES*8/2];
/* maximum major axis length is
1/2 screen width, because we're
assuming no clipping is needed */
/* Draws a circle of radius Radius in color Color centered at
* screen coordinate (X,Y) */
void DrawCircle(int X, int Y, int Radius, int Color) {
int MajorAxis, MinorAxis;
unsigned long RadiusSqMinusMajorAxisSq, MinorAxisSquaredThreshold;
unsigned char *PixListPtr, OriginalGCMode;
/* Set drawing color via set/reset */
outpw(GC_INDEX, (0x0F << 8) | SET_RESET_ENABLE_INDEX);
/* enable set/reset for all planes */
outpw(GC_INDEX, (Color << 8) | SET_RESET_INDEX);
/* set set/reset (drawing) color */
#if ISVGA
/* Remember original read/write mode & select
read mode 1/write mode 3, with Color Don't Care
set to ignore all planes and therefore always return 0xFF */
outp(GC_INDEX, GC_MODE_INDEX);
OriginalGCMode = inp(GC_INDEX + 1);
outp(GC_INDEX+1, OriginalGCMode | 0x0B);
outpw(GC_INDEX, (0x00 << 8) | COLOR_DONT_CARE);
outpw(GC_INDEX, (0xFF << 8) | BIT_MASK_INDEX);
#else
outp(GC_INDEX, BIT_MASK_INDEX); /* leave the GC Index reg pointing
to the Bit Mask reg */
#endif
/* Set up to draw the circle by setting the initial point to one
end of the 1/8th of a circle arc we'll draw */
MajorAxis = 0;
MinorAxis = Radius;
/* Set initial Radius**2 - MajorAxis**2 (MajorAxis is initially 0) */
RadiusSqMinusMajorAxisSq = (unsigned long) Radius * Radius;
/* Set threshold for minor axis movement at (MinorAxis - 0.5)**2 */
MinorAxisSquaredThreshold = (unsigned long) MinorAxis * MinorAxis -
MinorAxis;
/* Calculate all points along an arc of 1/8th of the circle.
Results are placed in PixList */
MajorAxis = GenerateOctant(PixList, MajorAxis, MinorAxis,
RadiusSqMinusMajorAxisSq, MinorAxisSquaredThreshold);
/* Now draw each of the 8 symmetries of the octant in turn */
/* Draw the octants for which Y is the major axis */
DrawVOctant(X-Radius,Y,MajorAxis,-SCREEN_WIDTH_IN_BYTES,1,PixList);
DrawVOctant(X-Radius,Y,MajorAxis,SCREEN_WIDTH_IN_BYTES,1,PixList);
DrawVOctant(X+Radius,Y,MajorAxis,-SCREEN_WIDTH_IN_BYTES,0,PixList);
DrawVOctant(X+Radius,Y,MajorAxis,SCREEN_WIDTH_IN_BYTES,0,PixList);
/* Draw the octants for which X is the major axis */
DrawHOctant(X,Y-Radius,MajorAxis,SCREEN_WIDTH_IN_BYTES,0,PixList);
DrawHOctant(X,Y-Radius,MajorAxis,SCREEN_WIDTH_IN_BYTES,1,PixList);
DrawHOctant(X,Y+Radius,MajorAxis,-SCREEN_WIDTH_IN_BYTES,0, PixList);
DrawHOctant(X,Y+Radius,MajorAxis,-SCREEN_WIDTH_IN_BYTES,1, PixList);
#if ISVGA
/* Restore original write mode */
outpw(GC_INDEX, (OriginalGCMode << 8) | GC_MODE_INDEX);
/* Restore normal Color Don't Care setting */
outpw(GC_INDEX, (0x0F << 8) | COLOR_DONT_CARE);
#else
/* Reset the Bit Mask register to normal */
outp(GC_INDEX + 1, 0xFF);
#endif
/* Turn off set/reset enable */
outpw(GC_INDEX, (0x00 << 8) | SET_RESET_ENABLE_INDEX);
}