www.pudn.com > XAnalogClock_demo.zip > WuLine.cpp
//
// Antialiasing: Wu Algorithm by .Suchit
// http://www.codeproject.com/gdi/antialias.asp
//
#include "stdafx.h"
#include "WuLine.h"
void DrawWuLine(CDC *pDC, int X0, int Y0, int X1, int Y1, COLORREF clrLine)
{
/* Make sure the line runs top to bottom */
if (Y0 > Y1)
{
int Temp = Y0; Y0 = Y1; Y1 = Temp;
Temp = X0; X0 = X1; X1 = Temp;
}
/* Draw the initial pixel, which is always exactly intersected by
the line and so needs no weighting */
pDC->SetPixel(X0, Y0, clrLine);
int XDir, DeltaX = X1 - X0;
if(DeltaX >= 0)
{
XDir = 1;
}
else
{
XDir = -1;
DeltaX = 0 - DeltaX; /* make DeltaX positive */
}
/* Special-case horizontal, vertical, and diagonal lines, which
require no weighting because they go right through the center of
every pixel */
int DeltaY = Y1 - Y0;
if (DeltaY == 0)
{
/* Horizontal line */
while (DeltaX-- != 0)
{
X0 += XDir;
pDC->SetPixel(X0, Y0, clrLine);
}
return;
}
if (DeltaX == 0)
{
/* Vertical line */
do
{
Y0++;
pDC->SetPixel(X0, Y0, clrLine);
} while (--DeltaY != 0);
return;
}
if (DeltaX == DeltaY)
{
/* Diagonal line */
do
{
X0 += XDir;
Y0++;
pDC->SetPixel(X0, Y0, clrLine);
} while (--DeltaY != 0);
return;
}
unsigned short ErrorAdj;
unsigned short ErrorAccTemp, Weighting;
/* Line is not horizontal, diagonal, or vertical */
unsigned short ErrorAcc = 0; /* initialize the line error accumulator to 0 */
BYTE rl = GetRValue(clrLine);
BYTE gl = GetGValue(clrLine);
BYTE bl = GetBValue(clrLine);
double grayl = rl * 0.299 + gl * 0.587 + bl * 0.114;
/* Is this an X-major or Y-major line? */
if (DeltaY > DeltaX)
{
/* Y-major line; calculate 16-bit fixed-point fractional part of a
pixel that X advances each time Y advances 1 pixel, truncating the
result so that we won't overrun the endpoint along the X axis */
ErrorAdj = (unsigned short)
(((unsigned long) DeltaX << 16) / (unsigned long) DeltaY);
/* Draw all pixels other than the first and last */
while (--DeltaY)
{
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
ErrorAcc = (unsigned short)(ErrorAcc + ErrorAdj); /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp)
{
/* The error accumulator turned over, so advance the X coord */
X0 += XDir;
}
Y0++; /* Y-major, so always advance Y */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = (unsigned short) (ErrorAcc >> 8);
ASSERT(Weighting < 256);
ASSERT((Weighting ^ 255) < 256);
COLORREF clrBackGround = ::GetPixel(pDC->m_hDC, X0, Y0);
BYTE rb = GetRValue(clrBackGround);
BYTE gb = GetGValue(clrBackGround);
BYTE bb = GetBValue(clrBackGround);
double grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
BYTE rr = (rb > rl ? ((BYTE)(((double)(grayl gl ? ((BYTE)(((double)(grayl bl ? ((BYTE)(((double)(graylSetPixel(X0, Y0, RGB(rr, gr, br));
clrBackGround = ::GetPixel(pDC->m_hDC, X0 + XDir, Y0);
rb = GetRValue(clrBackGround);
gb = GetGValue(clrBackGround);
bb = GetBValue(clrBackGround);
grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
rr = (rb > rl ? ((BYTE)(((double)(grayl gl ? ((BYTE)(((double)(grayl bl ? ((BYTE)(((double)(graylSetPixel(X0 + XDir, Y0, RGB(rr, gr, br));
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
pDC->SetPixel(X1, Y1, clrLine);
return;
}
/* It's an X-major line; calculate 16-bit fixed-point fractional part of a
pixel that Y advances each time X advances 1 pixel, truncating the
result to avoid overrunning the endpoint along the X axis */
ErrorAdj = (unsigned short)(((unsigned long) DeltaY << 16) / (unsigned long) DeltaX);
/* Draw all pixels other than the first and last */
while (--DeltaX)
{
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
ErrorAcc = (unsigned short)(ErrorAcc + ErrorAdj); /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp)
{
/* The error accumulator turned over, so advance the Y coord */
Y0++;
}
X0 += XDir; /* X-major, so always advance X */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = (unsigned short) (ErrorAcc >> 8);
ASSERT(Weighting < 256);
ASSERT((Weighting ^ 255) < 256);
COLORREF clrBackGround = ::GetPixel(pDC->m_hDC, X0, Y0);
BYTE rb = GetRValue(clrBackGround);
BYTE gb = GetGValue(clrBackGround);
BYTE bb = GetBValue(clrBackGround);
double grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
BYTE rr = (rb > rl ? ((BYTE)(((double)(grayl gl ? ((BYTE)(((double)(grayl bl ? ((BYTE)(((double)(graylSetPixel(X0, Y0, RGB(rr, gr, br));
clrBackGround = ::GetPixel(pDC->m_hDC, X0, Y0 + 1);
rb = GetRValue(clrBackGround);
gb = GetGValue(clrBackGround);
bb = GetBValue(clrBackGround);
grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
rr = (rb > rl ? ((BYTE)(((double)(grayl gl ? ((BYTE)(((double)(grayl bl ? ((BYTE)(((double)(graylSetPixel(X0, Y0 + 1, RGB(rr, gr, br));
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
pDC->SetPixel(X1, Y1, clrLine);
}