home *** CD-ROM | disk | FTP | other *** search
- _GRAPHICS PROGRAMMING COLUMN_
- by Michael Abrash
-
- [LISTING ONE]
-
- /* Looks for a Sierra Hicolor DAC; if one is present, puts the VGA into the
- specified Hicolor (32K color) mode. Relies on the Tseng Labs ET4000 BIOS and
- hardware; probably will not work on adapters built around other VGA chips.
- Returns 1 for success, 0 for failure; failure can result from no Hicolor DAC,
- too little display memory, or lack of an ET4000. Tested with Borland C++ 2.
- 0 in C mode in the small model. */
-
- #include <dos.h>
- #define DAC_MASK 0x3C6 /* DAC pixel mask reg address, also Sierra
- command reg address when enabled */
- #define DAC_WADDR 0x3C8 /* DAC write address reg address */
-
- /* Mode selections: 0x2D=640x350; 0x2E=640x480; 0x2F=640x400; 0x30=800x600 */
- int SetHCMode(int Mode) {
- int i, Temp1, Temp2, Temp3;
- union REGS regset;
-
- /* See if a Sierra SC1148X Hicolor DAC is present, by trying to
- program and then read back the DAC's command register. (Shouldn't be
- necessary when using the BIOS Get DAC Type function, but the BIOS function
- locks up some computers, so it's safer to check the hardware first) */
- inp(DAC_WADDR); /* reset the Sierra command reg enable sequence */
- for (i=0; i<4; i++) inp(DAC_MASK); /* enable command reg access */
- outp(DAC_MASK, 0x00); /* set command reg (if present) to 0x00, and
- reset command reg enable sequence */
- outp(DAC_MASK, 0xFF); /* command reg access no longer enabled;
- set pixel mask register to 0xFF */
- for (i=0; i<4; i++) inp(DAC_MASK); /* enable command reg access */
- /* If this is a Hicolor DAC, we should read back the 0 in the
- command reg; otherwise we get the 0xFF in the pixel mask reg */
- i = inp(DAC_MASK); inp(DAC_WADDR); /* reset enable sequence */
- if (i == 0xFF) return(0);
-
- /* Check for a Tseng Labs ET4000 by poking unique regs, (assumes
- VGA configured for color, w/CRTC addressing at 3D4/5) */
- outp(0x3BF, 3); outp(0x3D8, 0xA0); /* unlock extended registers */
- /* Try toggling AC R16 bit 4 and seeing if it takes */
- inp(0x3DA); outp(0x3C0, 0x16 | 0x20);
- outp(0x3C0, ((Temp1 = inp(0x3C1)) | 0x10)); Temp2 = inp(0x3C1);
- outp(0x3C0, 0x16 | 0x20); outp(0x3C0, (inp(0x3C1) & ~0x10));
- Temp3 = inp(0x3C1); outp(0x3C0, 0x16 | 0x20);
- outp(0x3C0, Temp1); /* restore original AC R16 setting */
- /* See if the bit toggled; if so, it's an ET3000 or ET4000 */
- if ((Temp3 & 0x10) || !(Temp2 & 0x10)) return(0);
- outp(0x3D4, 0x33); Temp1 = inp(0x3D5); /* get CRTC R33 setting */
- outp(0x3D5, 0x0A); Temp2 = inp(0x3D5); /* try writing to CRTC */
- outp(0x3D5, 0x05); Temp3 = inp(0x3D5); /* R33 */
- outp(0x3D5, Temp1); /* restore original CRTC R33 setting */
- /* If the register was writable, it's an ET4000 */
- if ((Temp3 != 0x05) || (Temp2 != 0x0A)) return(0);
-
- /* See if a Sierra SC1148X Hicolor DAC is present by querying the
- (presumably) ET4000-compatible BIOS. Not really necessary after
- the hardware check above, but generally more useful; in the
- future it will return information about other high-color DACs */
- regset.x.ax = 0x10F1; /* Get DAC Type BIOS function # */
- int86(0x10, ®set, ®set); /* ask BIOS for the DAC type */
- if (regset.x.ax != 0x0010) return(0); /* function not supported */
- switch (regset.h.bl) {
- case 0: return(0); /* normal DAC (non-Hicolor) */
- case 1: break; /* Sierra SC1148X 15-bpp Hicolor DAC */
- default: return(0); /* other high-color DAC */
- }
-
- /* Set Hicolor mode */
- regset.x.ax = 0x10F0; /* Set High-Color Mode BIOS function # */
- regset.h.bl = Mode; /* desired resolution */
- int86(0x10, ®set, ®set); /* have BIOS enable Hicolor mode */
- return (regset.x.ax == 0x0010); /* 1 for success, 0 for failure */
- }
-
-
-
-
- [LISTING TWO]
-
- /* Demonstrates non-antialiased drawing in 640x480 Hicolor (32K color) mode on
- an ET4000-based SuperVGA with a Sierra Hicolor DAC installed. Tested with
- Borland C++ 2.0 in C mode in the small model. */
-
- #include <conio.h>
- #include <dos.h>
- #include "polygon.h"
- /* Draws the polygon described by the point list PointList in color
- Color, with all vertices offset by (x,y) */
- #define DRAW_POLYGON(PointList,Color,x,y) { \
- Polygon.Length = sizeof(PointList)/sizeof(struct Point); \
- Polygon.PointPtr = PointList; \
- FillCnvxPolyDrvr(&Polygon, Color, x, y, DrawHCLineList);}
-
- void main(void);
- extern int SetHCMode(int);
- extern int FillCnvxPolyDrvr(struct PointListHeader *, int, int, int,
- void (*)());
- extern void DrawHCLineList(struct HLineList *, int);
- int BitmapWidthInBytes = 640*2; /* # of bytes per raster line */
-
- void main()
- {
- struct PointListHeader Polygon;
- static struct Point Face0[] = {{396,276},{422,178},{338,88},{288,178}};
- static struct Point Face1[] = {{306,300},{396,276},{288,178},{210,226}};
- static struct Point Face2[] = {{338,88},{266,146},{210,226},{288,178}};
- union REGS regset;
-
- /* Attempt to enable 640x480 Hicolor mode */
- if (SetHCMode(0x2E) == 0)
- { printf("No Hicolor DAC detected\n"); exit(0); };
-
- /* Draw the cube */
- DRAW_POLYGON(Face0, 0x1F, 0, 0); /* full-intensity blue */
- DRAW_POLYGON(Face1, 0x1F << 5, 0, 0); /* full-intensity green */
- DRAW_POLYGON(Face2, 0x1F << 10, 0, 0); /* full-intensity red */
- getch(); /* wait for a keypress */
-
- /* Return to text mode and exit */
- regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
- int86(0x10, ®set, ®set);
- }
-
-
-
-
- [LISTING THREE]
-
- /* Draws all pixels in the list of horizontal lines passed in, in Hicolor
- (32K color) mode on an ET4000-based SuperVGA. Uses a slow pixel-by-pixel
- approach. Tested with Borland C++ 2.0 in C mode in the small model. */
-
- #include <dos.h>
- #include "polygon.h"
- #define SCREEN_SEGMENT 0xA000
- #define GC_SEGMENT_SELECT 0x3CD
-
- void DrawPixel(int, int, int);
- extern int BitmapWidthInBytes; /* # of pixels per line */
-
- void DrawHCLineList(struct HLineList * HLineListPtr,
- int Color)
- {
- struct HLine *HLinePtr;
- int Y, X;
-
- /* Point to XStart/XEnd descriptor for the first (top) horizontal line */
- HLinePtr = HLineListPtr->HLinePtr;
- /* Draw each horizontal line in turn, starting with the top one and
- advancing one line each time */
- for (Y = HLineListPtr->YStart; Y < (HLineListPtr->YStart +
- HLineListPtr->Length); Y++, HLinePtr++) {
- /* Draw each pixel in the current horizontal line in turn,
- starting with the leftmost one */
- for (X = HLinePtr->XStart; X <= HLinePtr->XEnd; X++)
- DrawPixel(X, Y, Color);
- }
- }
-
- /* Draws the pixel at (X, Y) in color Color in Hicolor mode on an
- ET4000-based SuperVGA */
- void DrawPixel(int X, int Y, int Color) {
- unsigned int far *ScreenPtr, Bank;
- unsigned long BitmapAddress;
-
- /* Full bitmap address of pixel, as measured from address 0 to
- address 0xFFFFF. (X << 1) because pixels are 2 bytes in size */
- BitmapAddress = (unsigned long) Y * BitmapWidthInBytes + (X << 1);
- /* Map in the proper bank. Bank # is upper word of bitmap addr */
- Bank = *(((unsigned int *)&BitmapAddress) + 1);
- /* Upper nibble is read bank #, lower nibble is write bank # */
- outp(GC_SEGMENT_SELECT, (Bank << 4) | Bank);
- /* Draw into the bank */
- FP_SEG(ScreenPtr) = SCREEN_SEGMENT;
- FP_OFF(ScreenPtr) = *((unsigned int *)&BitmapAddress);
- *ScreenPtr = (unsigned int)Color;
- }
-
-
-
-
- [LISTING FOUR]
-
- ; Draws all pixels in the list of horizontal lines passed in, in
- ; Hicolor (32K color) mode on an ET4000-based SuperVGA. Uses REP STOSW
- ; to fill each line. Tested with TASM 2.0. C near-callable as:
- ; void DrawHCLineList(struct HLineList * HLineListPtr, int Color);
-
- SCREEN_SEGMENT equ 0a000h
- GC_SEGMENT_SELECT equ 03cdh
-
- HLine struc
- XStart dw ? ;X coordinate of leftmost pixel in line
- XEnd dw ? ;X coordinate of rightmost pixel in line
- HLine ends
-
- HLineList struc
- Lngth dw ? ;# of horizontal lines
- YStart dw ? ;Y coordinate of topmost line
- HLinePtr dw ? ;pointer to list of horz lines
- HLineList ends
-
- Parms struc
- dw 2 dup(?) ;return address & pushed BP
- HLineListPtr dw ? ;pointer to HLineList structure
- Color dw ? ;color with which to fill
- Parms ends
-
- ; Advances both the read and write windows to the next 64K bank.
- ; Note: Theoretically, a delay between IN and OUT may be needed under
- ; some circumstances to avoid accessing the VGA chip too quickly, but
- ; in actual practice, I haven't found any delay to be required.
- INCREMENT_BANK macro
- push ax ;preserve fill color
- push dx ;preserve scan line start pointer
- mov dx,GC_SEGMENT_SELECT
- in al,dx ;get the current segment select
- add al,11h ;increment both the read & write banks
- out dx,al ;set the new bank #
- pop dx ;restore scan line start pointer
- pop ax ;restore fill color
- endm
-
- .model small
- .data
- extrn _BitmapWidthInBytes:word
- .code
- public _DrawHCLineList
- align 2
- _DrawHCLineList proc near
- push bp ;preserve caller's stack frame
- mov bp,sp ;point to our stack frame
- push si ;preserve caller's register variables
- push di
- cld ;make string instructions inc pointers
- mov ax,SCREEN_SEGMENT
- mov es,ax ;point ES to display memory for REP STOS
- mov si,[bp+HLineListPtr] ;point to the line list
- mov ax,[_BitmapWidthInBytes] ;point to the start of the
- mul [si+YStart] ; first scan line on which to draw
- mov di,ax ;ES:DI points to first scan line to
- mov al,dl ; draw; AL is the initial bank #
- ;upper nibble of AL is read bank #,
- mov cl,4 ; lower nibble is write bank # (only
- shl dl,cl ; the write bank is really needed for
- or al,dl ; this module, but it's less confusing
- ; to point both to the same place)
- mov dx,GC_SEGMENT_SELECT
- out dx,al ;set the initial bank
- mov dx,di ;ES:DX points to first scan line
- mov bx,[si+HLinePtr] ;point to the XStart/XEnd descriptor
- ; for the first (top) horizontal line
- mov si,[si+Lngth] ;# of scan lines to draw
- and si,si ;are there any lines to draw?
- jz FillDone ;no, so we're done
- mov ax,[bp+Color] ;color with which to fill
- mov bp,[_BitmapWidthInBytes] ;so we can keep everything
- ; in registers inside the loop
- ;***stack frame pointer destroyed!***
- FillLoop:
- mov di,[bx+XStart] ;left edge of fill on this line
- mov cx,[bx+XEnd] ;right edge of fill
- sub cx,di
- jl LineFillDone ;skip if negative width
- inc cx ;# of pixels to fill on this line
- add di,di ;*2 because pixels are 2 bytes in size
- add dx,bp ;do we cross a bank during this line?
- jnc NormalFill ;no
- jz NormalFill ;no
- ;yes, there is a bank crossing on this
- ; line; figure out where
- sub dx,bp ;point back to start of line
- add di,dx ;offset of left edge of fill
- jc CrossBankBeforeFilling ;raster splits before the left
- ; edge of fill
- add cx,cx ;fill width in bytes (pixels * 2)
- add di,cx ;do we split during the fill area?
- jnc CrossBankAfterFilling ;raster splits after the right
- jz CrossBankAfterFilling ; edge of fill
- ;bank boundary falls within fill area;
- ; draw in two parts, one in each bank
- sub di,cx ;point back to start of fill area
- neg di ;# of bytes left before split
- sub cx,di ;# of bytes to fill to the right of
- ; the bank split
- push cx ;remember right-of-split fill width
- mov cx,di ;# of left-of-split bytes to fill
- shr cx,1 ;# of left-of-split words to fill
- neg di ;offset at which to start filling
- rep stosw ;fill left-of-split portion of line
- pop cx ;get back right-of-split fill width
- shr cx,1 ;# of right-of-split words to fill
- ;advance to the next bank
- INCREMENT_BANK ;point to the next bank (DI already
- ; points to offset 0, as desired)
- rep stosw ;fill right-of-split portion of line
- add dx,bp ;point to the next scan line
- jmp short CountDownLine ; (already advanced the bank)
- ;======================================================================
- align 2 ;dfill area is entirely to the left of
- CrossBankAfterFilling: ; the bank boundary
- sub di,cx ;point back to start of fill area
- shr cx,1 ;CX = fill width in pixels
- jmp short FillAndAdvance ;doesn't split until after the
- ; fill area, so handle normally
- ;======================================================================
- align 2 ;fill area is entirely to the right of
- CrossBankBeforeFilling: ; the bank boundary
- INCREMENT_BANK ;first, point to the next bank, where
- ; the fill area resides
- rep stosw ;fill this scan line
- add dx,bp ;point to the next scan line
- jmp short CountDownLine ; (already advanced the bank)
- ;======================================================================
- align 2 ;no bank boundary problems; just fill
- NormalFill: ; normally
- sub dx,bp ;point back to start of line
- add di,dx ;offset of left edge of fill
- FillAndAdvance:
- rep stosw ;fill this scan line
- LineFillDone:
- add dx,bp ;point to the next scan line
- jnc CountDownLine ;didn't cross a bank boundary
- INCREMENT_BANK ;did cross, so point to the next bank
- CountDownLine:
- add bx,size HLine ;point to the next line descriptor
- dec si ;count off lines to fill
- jnz FillLoop
- FillDone:
- pop di ;restore caller's register variables
- pop si
- pop bp ;restore caller's stack frame
- ret
- ;======================================================================
- _DrawHCLineList endp
- end
-
-
-
-
- [LISTING FIVE]
-
- /* Demonstrates unweighted antialiased drawing in 640x480 Hicolor (32K color)
- mode. Tested with Borland C++ 2.0 in C mode in the small model. */
-
- #include <conio.h>
- #include <dos.h>
- #include <stdlib.h>
- #include <string.h>
- #include "polygon.h"
- /* Draws the polygon described by the point list PointList in the
- color specified by RED, GREEN, AND BLUE, with all vertices
- offset by (x,y), to ScanLineBuffer, at ResMul multiple of
- horizontal and vertical resolution. The address of ColorTemp is
- cast to an int to satisfy the prototype for FillCnvxPolyDrvr; this
- trick will work only in a small data model */
- #define DRAW_POLYGON_HIGH_RES(PointList,RED,GREEN,BLUE,x,y,ResMul) { \
- Polygon.Length = sizeof(PointList)/sizeof(struct Point); \
- Polygon.PointPtr = PointTemp; \
- /* Multiply all vertical & horizontal coordinates */ \
- for (k=0; k<sizeof(PointList)/sizeof(struct Point); k++) { \
- PointTemp[k].X = PointList[k].X * ResMul; \
- PointTemp[k].Y = PointList[k].Y * ResMul; \
- } \
- ColorTemp.Red=RED; ColorTemp.Green=GREEN; ColorTemp.Blue=BLUE; \
- FillCnvxPolyDrvr(&Polygon, (int)&ColorTemp, x, y, DrawBandedList);}
- #define SCREEN_WIDTH 640
- #define SCREEN_SEGMENT 0xA000
-
- void main(void);
- extern void DrawPixel(int, int, char);
- extern void DrawBandedList(struct HLineList *, struct RGB *);
- extern int SetHCMode(int);
-
- /* Table of gamma corrected mappings of linear color intensities in
- the range 0-255 to the nearest pixel values in the range 0-31,
- assuming a gamma of 2.3 */
- static unsigned char ColorMappings[] = {
- 0, 3, 4, 4, 5, 6, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9,10,10,10,
- 10,10,11,11,11,11,11,12,12,12,12,12,13,13,13,13,13,13,14,14,
- 14,14,14,14,14,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,
- 17,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,
- 19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,21,
- 21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,
- 22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,
- 25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,
- 27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,
- 28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,
- 29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,30,30,30,
- 30,30,30,30,30,30,31,31,31,31,31,31,31,31,31,31};
- /* Pointer to buffer in which high-res scanned data will reside */
- struct RGB *ScanLineBuffer;
- int ScanBandStart, ScanBandEnd; /* top & bottom of each high-res
- band we'll draw to ScanLineBuffer */
- int ScanBandWidth; /* # subpixels across each scan band */
- int BitmapWidthInBytes = 640*2; /* # of bytes per raster line in
- Hicolor VGA display memory */
- void main()
- {
- int i, j, k, m, Red, Green, Blue, jXRes, kXWidth;
- int SubpixelsPerMegapixel;
- unsigned int Megapixel, ResolutionMultiplier;
- long BufferSize;
- struct RGB ColorTemp;
- struct PointListHeader Polygon;
- struct Point PointTemp[4];
- static struct Point Face0[] =
- {{396,276},{422,178},{338,88},{288,178}};
- static struct Point Face1[] =
- {{306,300},{396,276},{288,178},{210,226}};
- static struct Point Face2[] =
- {{338,88},{266,146},{210,226},{288,178}};
- int LeftBound=210, RightBound=422, TopBound=88, BottomBound=300;
- union REGS regset;
-
- printf("Subpixel resolution multiplier:");
- scanf("%d", &ResolutionMultiplier);
- SubpixelsPerMegapixel = ResolutionMultiplier*ResolutionMultiplier;
- ScanBandWidth = SCREEN_WIDTH*ResolutionMultiplier;
-
- /* Get enough space for one scan line scanned out at high
- resolution horz and vert (each pixel is 4 bytes) */
- if ((BufferSize = (long)ScanBandWidth*4*ResolutionMultiplier) >
- 0xFFFF) {
- printf("Band won't fit in one segment\n"); exit(0); }
- if ((ScanLineBuffer = malloc((int)BufferSize)) == NULL) {
- printf("Couldn't get memory\n"); exit(0); }
-
- /* Attempt to enable 640x480 Hicolor mode */
- if (SetHCMode(0x2E) == 0)
- { printf("No Hicolor DAC detected\n"); exit(0); };
-
- /* Scan out the polygons at high resolution one screen scan line at
- a time (ResolutionMultiplier high-res scan lines at a time) */
- for (i=TopBound; i<=BottomBound; i++) {
- /* Set the band dimensions for this pass */
- ScanBandEnd = (ScanBandStart = i*ResolutionMultiplier) +
- ResolutionMultiplier - 1;
- /* Clear the drawing buffer */
- memset(ScanLineBuffer, 0, BufferSize);
- /* Draw the current band of the cube to the scan line buffer */
- DRAW_POLYGON_HIGH_RES(Face0,0xFF,0,0,0,0,ResolutionMultiplier);
- DRAW_POLYGON_HIGH_RES(Face1,0,0xFF,0,0,0,ResolutionMultiplier);
- DRAW_POLYGON_HIGH_RES(Face2,0,0,0xFF,0,0,ResolutionMultiplier);
-
- /* Coalesce subpixels into normal screen pixels (megapixels) and draw them */
- for (j=LeftBound; j<=RightBound; j++) {
- jXRes = j*ResolutionMultiplier;
- /* For each screen pixel, sum all the corresponding
- subpixels, for each color component */
- for (k=Red=Green=Blue=0; k<ResolutionMultiplier; k++) {
- kXWidth = k*ScanBandWidth;
- for (m=0; m<ResolutionMultiplier; m++) {
- Red += ScanLineBuffer[jXRes+kXWidth+m].Red;
- Green += ScanLineBuffer[jXRes+kXWidth+m].Green;
- Blue += ScanLineBuffer[jXRes+kXWidth+m].Blue;
- }
- }
- /* Calc each color component's average brightness; convert
- that into a gamma corrected portion of a Hicolor pixel,
- then combine the colors into one Hicolor pixel */
- Red = ColorMappings[Red/SubpixelsPerMegapixel];
- Green = ColorMappings[Green/SubpixelsPerMegapixel];
- Blue = ColorMappings[Blue/SubpixelsPerMegapixel];
- Megapixel = (Red << 10) + (Green << 5) + Blue;
- DrawPixel(j, i, Megapixel);
- }
- }
- getch(); /* wait for a keypress */
-
- /* Return to text mode and exit */
- regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
- int86(0x10, ®set, ®set);
- }
-
-
-
-
- [LISTING SIX]
-
- /* Draws pixels from the list of horizontal lines passed in, to a 32-bpp
- buffer; drawing takes place only for scan lines between ScanBandStart and
- ScanBandEnd, inclusive; drawing goes to ScanLineBuffer, with the scan line at
- ScanBandStart mapping to the first scan line in ScanLineBuffer. Note that
- Color here points to an RGB structure that maps directly to the buffer's pixel
- format, rather than containing a 16-bit integer. Tested with Borland C++ 2.0
- in C mode in the small model */
-
- #include "polygon.h"
-
- extern struct RGB *ScanLineBuffer; /* drawing goes here */
- extern int ScanBandStart, ScanBandEnd; /* limits of band to draw */
- extern int ScanBandWidth; /* # of subpixels across scan band */
-
- void DrawBandedList(struct HLineList * HLineListPtr,
- struct RGB *Color)
- {
- struct HLine *HLinePtr;
- int Length, Width, YStart = HLineListPtr->YStart, i;
- struct RGB *BufferPtr, *WorkingBufferPtr;
-
- /* Done if fully off the bottom or top of the band */
- if (YStart > ScanBandEnd) return;
- Length = HLineListPtr->Length;
- if ((YStart + Length) <= ScanBandStart) return;
-
- /* Point to XStart/XEnd descriptor for the first (top) horizontal line */
- HLinePtr = HLineListPtr->HLinePtr;
-
- /* Confine drawing to the specified band */
- if (YStart < ScanBandStart) {
- /* Skip ahead to the start of the band */
- Length -= ScanBandStart - YStart;
- HLinePtr += ScanBandStart - YStart;
- YStart = ScanBandStart;
- }
- if (Length > (ScanBandEnd - YStart + 1))
- Length = ScanBandEnd - YStart + 1;
-
- /* Point to the start of the first scan line on which to draw */
- BufferPtr = ScanLineBuffer + (YStart-ScanBandStart)*ScanBandWidth;
-
- /* Draw each horizontal line within the band in turn, starting with
- the top one and advancing one line each time */
- while (Length-- > 0) {
- /* Fill whole horiz line with Color if it has positive width */
- if ((Width = HLinePtr->XEnd - HLinePtr->XStart + 1) > 0) {
- WorkingBufferPtr = BufferPtr + HLinePtr->XStart;
- for (i = 0; i < Width; i++) *WorkingBufferPtr++ = *Color;
- }
- HLinePtr++; /* point to next scan line X info */
- BufferPtr += ScanBandWidth; /* point to start of next line */
- }
- }
-
-
-
-
- [LISTING SEVEN]
-
- /* POLYGON.H: Header file for polygon-filling code */
-
- /* Describes a single point (used for a single vertex) */
- struct Point {
- int X; /* X coordinate */
- int Y; /* Y coordinate */
- };
-
- /* Describes a series of points (used to store a list of vertices that
- describe a polygon; each vertex is assumed to connect to the two adjacent
- vertices, and the last vertex is assumed to connect to the first) */
- struct PointListHeader {
- int Length; /* # of points */
- struct Point * PointPtr; /* pointer to list of points */
- };
-
- /* Describes the beginning and ending X coordinates of a single
- horizontal line */
- struct HLine {
- int XStart; /* X coordinate of leftmost pixel in line */
- int XEnd; /* X coordinate of rightmost pixel in line */
- };
-
- /* Describes a Length-long series of horizontal lines, all assumed to be on
- contiguous scan lines starting at YStart and proceeding downward (used to
- describe scan-converted polygon to low-level hardware-dependent drawing code)*/
- struct HLineList {
- int Length; /* # of horizontal lines */
- int YStart; /* Y coordinate of topmost line */
- struct HLine * HLinePtr; /* pointer to list of horz lines */
- };
-
- /* Describes a color as an RGB triple, plus one byte for other info */
- struct RGB { unsigned char Red, Green, Blue, Spare; };
-
-