home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / gems / graphics / aalines.c next >
Text File  |  1992-04-09  |  4KB  |  148 lines

  1. /*
  2. Rendering Anti-Aliased Lines
  3. by Kelvin Thompson
  4. from "Graphics Gems", Academic Press, 1990
  5. */
  6.  
  7. /* HARDWARE ASSUMPTIONS:
  8. /*    * 32-bit, signed ints
  9. /*    * 8-bit pixels, with initialized color table
  10. /*    * pixels are memory mapped in a rectangular fashion */
  11.  
  12. /* FIXED-POINT DATA TYPE */
  13. typedef int FX;
  14. # define FX_FRACBITS 16  /* bits of fraction in FX format */
  15. # define FX_0        0   /* zero in fixed-point format */
  16.  
  17.  
  18. /* ASSUMED MACROS:
  19. /*   SWAPVARS(v1,v2) -- swaps the contents of two variables
  20. /*   PIXADDR(x,y) -- returns address of pixel at (x,y)
  21. /*   COVERAGE(FXdist) -- lookup macro for pixel coverage 
  22.         given perpendicular distance; takes a fixed-point
  23.         integer and returns an integer in the range [0,255]
  24. /*   SQRTFUNC(FXval) -- lookup macro for sqrt(1/(1+FXval^2))
  25.         accepts and returns fixed-point numbers
  26. /*   FIXMUL(FX1,FX2) -- multiplies two fixed-point numbers
  27.         and returns the product as a fixed-point number   */
  28.  
  29. /* BLENDING FUNCTION:
  30. /*  'cover' is coverage -- in the range [0,255]
  31. /*  'back' is background color -- in the range [0,255] */
  32. #define BLEND(cover,back) ((((255-(cover))*(back))>>8)+(cover))
  33.  
  34. /* LINE DIRECTION bits and tables */
  35. #define DIR_STEEP  1  /* set when abs(dy) > abs(dx) */
  36. #define DIR_NEGY   2  /* set whey dy < 0 */
  37.  
  38.  
  39. /* pixel increment values 
  40. /*   -- assume PIXINC(dx,dy) is a macro such that:
  41. /*   PIXADDR(x0,y0) + PIXINC(dx,dy) = PIXADDR(x0+dx,y0+dy)  */
  42. static int adj_pixinc[4] = 
  43.       { PIXINC(1,0), PIXINC(0,1), PIXINC(1,0), PIXINC(0,-1) };
  44. static int diag_pixinc[4] = 
  45.       { PIXINC(1,1), PIXINC(1,1), PIXINC(1,-1), PIXINC(1,-1) };
  46. static int orth_pixinc[4] = 
  47.       { PIXINC(0,1), PIXINC(1,0), PIXINC(0,-1), PIXINC(1,0) };
  48.  
  49. /* Global 'Pmax' is initialized elsewhere.  It is the
  50.    "maximum perpendicular distance" -- the sum of half the
  51.    line width and the effective pixel radius -- in fixed format */
  52. FX Pmax;
  53.  
  54.  
  55. /***************  FUNCTION ANTI_LINE  ***************/
  56.  
  57. void Anti_Line ( X1, Y1, X2, Y2 )
  58. int X1, Y1, X2, Y2;
  59. {
  60. int     Bvar,     /* decision variable for Bresenham's */
  61.         Bainc,   /* adjacent-increment for 'Bvar' */
  62.         Bdinc;   /* diagonal-increment for 'Bvar' */
  63. FX         Pmid,      /* perp distance at Bresenham's pixel */
  64.            Pnow,      /* perp distance at current pixel (ortho loop) */
  65.            Painc,     /* adjacent-increment for 'Pmid' */
  66.            Pdinc,     /* diagonal-increment for 'Pmid' */
  67.            Poinc;     /* orthogonal-increment for 'Pnow'--also equals 'k' */
  68. char     *mid_addr,   /* pixel address for Bresenham's pixel */
  69.          *now_addr;   /* pixel address for current pixel */
  70. int     addr_ainc,   /* adjacent pixel address offset */
  71.         addr_dinc,   /* diagonal pixel address offset */
  72.         addr_oinc;   /* orthogonal pixel address offset */
  73. int dx,dy,dir;        /* direction and deltas */
  74. FX slope;            /* slope of line */
  75. int temp;
  76.  
  77. /* rearrange ordering to force left-to-right */
  78. if     ( X1 > X2 )
  79.       { SWAPVARS(X1,X2);  SWAPVARS(Y1,Y2); }
  80.  
  81. /* init deltas */
  82. dx = X2 - X1;  /* guaranteed non-negative */
  83. dy = Y2 - Y1;
  84.  
  85.  
  86. /* calculate direction (slope category) */
  87. dir = 0;
  88. if ( dy < 0 )   { dir |= DIR_NEGY;  dy = -dy; }
  89. if ( dy > dx )  { dir |= DIR_STEEP; SWAPVARS(dx,dy); }
  90.  
  91. /* init address stuff */
  92. mid_addr = PIXADDR(X1,Y1);
  93. addr_ainc = adj_pixinc[dir];
  94. addr_dinc = diag_pixinc[dir];
  95. addr_oinc = orth_pixinc[dir];
  96.  
  97. /* perpendicular measures */
  98. slope =  (dy << FX_FRACBITS) / dx;
  99. Poinc = SQRTFUNC( slope );
  100. Painc = FIXMUL( slope, Poinc );
  101. Pdinc = Painc - Poinc;
  102. Pmid = FX_0;
  103.  
  104. /* init Bresenham's */
  105. Bainc = dy << 1;
  106. Bdinc = (dy-dx) << 1;
  107. Bvar = Bainc - dx;
  108.  
  109. do
  110.       {
  111.       /* do middle pixel */
  112.       *mid_addr = BLEND( COVERAGE(abs(Pmid)), *mid_addr );
  113.  
  114.       /* go up orthogonally */
  115.       for (
  116.           Pnow = Poinc-Pmid,  now_addr = mid_addr+addr_oinc;
  117.           Pnow < Pmax;
  118.           Pnow += Poinc,      now_addr += addr_oinc
  119.           )
  120.        *now_addr = BLEND( COVERAGE(Pnow), *now_addr );
  121.  
  122.       /* go down orthogonally */
  123.       for (
  124.           Pnow = Poinc+Pmid,  now_addr = mid_addr-addr_oinc;
  125.           Pnow < Pmax;
  126.           Pnow += Poinc,      now_addr -= addr_oinc
  127.           )
  128.        *now_addr = BLEND( COVERAGE(Pnow), *now_addr );
  129.  
  130.  
  131.       /* update Bresenham's */
  132.       if ( Bvar < 0 )
  133.         {
  134.         Bvar += Bainc;
  135.         mid_addr = (char *) ((int)mid_addr + addr_ainc);
  136.         Pmid += Painc;
  137.         }
  138.       else
  139.         {
  140.         Bvar += Bdinc;
  141.         mid_addr = (char *) ((int)mid_addr + addr_dinc);
  142.         Pmid += Pdinc;
  143.         }
  144.  
  145.       --dx;
  146.       } while ( dx >= 0 );
  147. }
  148.