home *** CD-ROM | disk | FTP | other *** search
- /*
- Rendering Anti-Aliased Lines
- by Kelvin Thompson
- from "Graphics Gems", Academic Press, 1990
- */
-
- /* HARDWARE ASSUMPTIONS:
- /* * 32-bit, signed ints
- /* * 8-bit pixels, with initialized color table
- /* * pixels are memory mapped in a rectangular fashion */
-
- /* FIXED-POINT DATA TYPE */
- typedef int FX;
- # define FX_FRACBITS 16 /* bits of fraction in FX format */
- # define FX_0 0 /* zero in fixed-point format */
-
-
- /* ASSUMED MACROS:
- /* SWAPVARS(v1,v2) -- swaps the contents of two variables
- /* PIXADDR(x,y) -- returns address of pixel at (x,y)
- /* COVERAGE(FXdist) -- lookup macro for pixel coverage
- given perpendicular distance; takes a fixed-point
- integer and returns an integer in the range [0,255]
- /* SQRTFUNC(FXval) -- lookup macro for sqrt(1/(1+FXval^2))
- accepts and returns fixed-point numbers
- /* FIXMUL(FX1,FX2) -- multiplies two fixed-point numbers
- and returns the product as a fixed-point number */
-
- /* BLENDING FUNCTION:
- /* 'cover' is coverage -- in the range [0,255]
- /* 'back' is background color -- in the range [0,255] */
- #define BLEND(cover,back) ((((255-(cover))*(back))>>8)+(cover))
-
- /* LINE DIRECTION bits and tables */
- #define DIR_STEEP 1 /* set when abs(dy) > abs(dx) */
- #define DIR_NEGY 2 /* set whey dy < 0 */
-
-
- /* pixel increment values
- /* -- assume PIXINC(dx,dy) is a macro such that:
- /* PIXADDR(x0,y0) + PIXINC(dx,dy) = PIXADDR(x0+dx,y0+dy) */
- static int adj_pixinc[4] =
- { PIXINC(1,0), PIXINC(0,1), PIXINC(1,0), PIXINC(0,-1) };
- static int diag_pixinc[4] =
- { PIXINC(1,1), PIXINC(1,1), PIXINC(1,-1), PIXINC(1,-1) };
- static int orth_pixinc[4] =
- { PIXINC(0,1), PIXINC(1,0), PIXINC(0,-1), PIXINC(1,0) };
-
- /* Global 'Pmax' is initialized elsewhere. It is the
- "maximum perpendicular distance" -- the sum of half the
- line width and the effective pixel radius -- in fixed format */
- FX Pmax;
-
-
- /*************** FUNCTION ANTI_LINE ***************/
-
- void Anti_Line ( X1, Y1, X2, Y2 )
- int X1, Y1, X2, Y2;
- {
- int Bvar, /* decision variable for Bresenham's */
- Bainc, /* adjacent-increment for 'Bvar' */
- Bdinc; /* diagonal-increment for 'Bvar' */
- FX Pmid, /* perp distance at Bresenham's pixel */
- Pnow, /* perp distance at current pixel (ortho loop) */
- Painc, /* adjacent-increment for 'Pmid' */
- Pdinc, /* diagonal-increment for 'Pmid' */
- Poinc; /* orthogonal-increment for 'Pnow'--also equals 'k' */
- char *mid_addr, /* pixel address for Bresenham's pixel */
- *now_addr; /* pixel address for current pixel */
- int addr_ainc, /* adjacent pixel address offset */
- addr_dinc, /* diagonal pixel address offset */
- addr_oinc; /* orthogonal pixel address offset */
- int dx,dy,dir; /* direction and deltas */
- FX slope; /* slope of line */
- int temp;
-
- /* rearrange ordering to force left-to-right */
- if ( X1 > X2 )
- { SWAPVARS(X1,X2); SWAPVARS(Y1,Y2); }
-
- /* init deltas */
- dx = X2 - X1; /* guaranteed non-negative */
- dy = Y2 - Y1;
-
-
- /* calculate direction (slope category) */
- dir = 0;
- if ( dy < 0 ) { dir |= DIR_NEGY; dy = -dy; }
- if ( dy > dx ) { dir |= DIR_STEEP; SWAPVARS(dx,dy); }
-
- /* init address stuff */
- mid_addr = PIXADDR(X1,Y1);
- addr_ainc = adj_pixinc[dir];
- addr_dinc = diag_pixinc[dir];
- addr_oinc = orth_pixinc[dir];
-
- /* perpendicular measures */
- slope = (dy << FX_FRACBITS) / dx;
- Poinc = SQRTFUNC( slope );
- Painc = FIXMUL( slope, Poinc );
- Pdinc = Painc - Poinc;
- Pmid = FX_0;
-
- /* init Bresenham's */
- Bainc = dy << 1;
- Bdinc = (dy-dx) << 1;
- Bvar = Bainc - dx;
-
- do
- {
- /* do middle pixel */
- *mid_addr = BLEND( COVERAGE(abs(Pmid)), *mid_addr );
-
- /* go up orthogonally */
- for (
- Pnow = Poinc-Pmid, now_addr = mid_addr+addr_oinc;
- Pnow < Pmax;
- Pnow += Poinc, now_addr += addr_oinc
- )
- *now_addr = BLEND( COVERAGE(Pnow), *now_addr );
-
- /* go down orthogonally */
- for (
- Pnow = Poinc+Pmid, now_addr = mid_addr-addr_oinc;
- Pnow < Pmax;
- Pnow += Poinc, now_addr -= addr_oinc
- )
- *now_addr = BLEND( COVERAGE(Pnow), *now_addr );
-
-
- /* update Bresenham's */
- if ( Bvar < 0 )
- {
- Bvar += Bainc;
- mid_addr = (char *) ((int)mid_addr + addr_ainc);
- Pmid += Painc;
- }
- else
- {
- Bvar += Bdinc;
- mid_addr = (char *) ((int)mid_addr + addr_dinc);
- Pmid += Pdinc;
- }
-
- --dx;
- } while ( dx >= 0 );
- }
-