Bresenham直线算法/Wu反走样实例

void NcLine ( int x0, int y0, 
int x1, int y1, uint p32BitVram, int pitch, uint color ) {

p32BitVram += (x0 << 2) + y0 * pitch;

int absX = x1 - x0,
absY = y1 - y0,

absXTemp = absX >> 31,
absYTemp = absY >> 31;

int vx_dir = ((absXTemp - ~absXTemp) << 2);
pitch = (pitch ^ absYTemp) - absYTemp,

absX = (absX ^ absXTemp) - absXTemp,
absY = (absY ^ absYTemp) - absYTemp;

int rtqX = absX << 1,
rtqY = absY << 1;

int error,
incEx, rtqL_Ex;

if (absX > absY) { /* near X */

error = rtqY - absX;
incEx = vx_dir + pitch;

rtqL_Ex = error - absX;
while (--absX) {
*cast (uint*) p32BitVram = color;
if (error < 0) {
p32BitVram += vx_dir;
error += rtqY;
} else {
p32BitVram += incEx;
error += rtqL_Ex;
}
} *cast (uint*) p32BitVram = color;
return;
}
error = rtqX - absY;
incEx = vx_dir + pitch;

rtqL_Ex = error - absY;
while (--absY) {
*cast (uint*) p32BitVram = color;
if (error < 0) {
p32BitVram += pitch;
error += rtqX;
} else {
p32BitVram += incEx;
error += rtqL_Ex;
}
} *cast (uint*) p32BitVram = color;
}

void WuLine ( uint * p32bitVram, uint VramPitch, int xPosStart, int yPosStart, int xPosEnd, int yPosEnd, uint clrLine ){ 

int XDir,
DeltaX,
DeltaY;

uint grayl, grayb,
ErrorAdj, ErrorAcc,
Weighting, ErrorAccTemp;

uint* LastEndWriteAddr = p32bitVram;

ubyte Mix[4];
ubyte Line[4];
ubyte Bg[4];

double WeightingShrink;

VramPitch >>= 2;

if (yPosStart > yPosEnd) {
int Temp = yPosEnd; yPosEnd = yPosStart; yPosStart = Temp;
Temp = xPosStart; xPosStart = xPosEnd; xPosEnd = Temp;
} *( p32bitVram += xPosStart + yPosStart * VramPitch ) = clrLine;

if ( ( DeltaX = xPosEnd - xPosStart ) >= 0 )
XDir = 1;
else
XDir = -1, DeltaX = -DeltaX;

if ( ( DeltaY = yPosEnd - yPosStart ) == 0 ) { /* Horizontal line */
if ( XDir > 0 ) {
while (--DeltaX != 0)
*(++p32bitVram) = clrLine;
*(++p32bitVram) = clrLine;
} else {
while (--DeltaX != 0)
*(--p32bitVram) = clrLine;
*(--p32bitVram) = clrLine;
} return;
} else if ( DeltaX == 0 ) { /* Vertical line */
do {
*(p32bitVram += VramPitch) = clrLine;
} while (--DeltaY != 0); return;
} else if ( DeltaX == DeltaY ) { /* Diagonal line */
if ( XDir > 0 ) {
do {
*(++p32bitVram += VramPitch) = clrLine;
} while (--DeltaY != 0);
} else /* Diagonal line Dec */ {
do {
*(--p32bitVram += VramPitch) = clrLine;
} while (--DeltaY != 0);
} return;
}

*cast (uint*) Line = clrLine, ErrorAcc = 0;

grayl = ( ( cast(uint) Line[2] << 2 ) + cast(uint) Line[1] * 5 + cast(uint) Line[0]);

if (DeltaY > DeltaX) {
ErrorAdj = cast(uint) ( ( cast(ulong) DeltaX << 32) / cast(ulong) DeltaY );

while (--DeltaY) {
ErrorAccTemp = ErrorAcc;

* cast (uint*) Bg = ((ErrorAcc += ErrorAdj) <= ErrorAccTemp ? * ( p32bitVram += VramPitch + XDir ) : * ( p32bitVram += VramPitch ) );

Weighting = ErrorAcc >> 24;

grayb = ( ( cast(uint) Bg[2] << 2 ) + cast(uint) Bg[1] * 5 + cast(uint) Bg[0] );

WeightingShrink = (grayl >= grayb ? Weighting ^ 0xFF : Weighting) / 255.0;

Mix[2] = ( Bg[2] > Line[2] ? ( cast(ubyte)( WeightingShrink * ( Bg[2] - Line[2] ) + Line[2] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[2] - Bg[2] ) + Bg[2] ) ) );
Mix[1] = ( Bg[1] > Line[1] ? ( cast(ubyte)( WeightingShrink * ( Bg[1] - Line[1] ) + Line[1] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[1] - Bg[1] ) + Bg[1] ) ) );
Mix[0] = ( Bg[0] > Line[0] ? ( cast(ubyte)( WeightingShrink * ( Bg[0] - Line[0] ) + Line[0] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[0] - Bg[0] ) + Bg[0] ) ) );

*( p32bitVram ) = *cast(uint*) Mix;
*cast(uint*) Bg = *( p32bitVram + XDir );

grayb = ( (cast(uint) Bg[2] << 2) + cast(uint) Bg[1] * 5 +cast(uint) Bg[0] );

WeightingShrink = (grayl < grayb ? Weighting ^ 0xFF : Weighting) / 255.0;

Mix[2] = ( Bg[2] > Line[2] ? ( cast(ubyte)( WeightingShrink * ( Bg[2] - Line[2] ) + Line[2] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[2] - Bg[2] ) + Bg[2] ) ) );
Mix[1] = ( Bg[1] > Line[1] ? ( cast(ubyte)( WeightingShrink * ( Bg[1] - Line[1] ) + Line[1] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[1] - Bg[1] ) + Bg[1] ) ) );
Mix[0] = ( Bg[0] > Line[0] ? ( cast(ubyte)( WeightingShrink * ( Bg[0] - Line[0] ) + Line[0] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[0] - Bg[0] ) + Bg[0] ) ) );

*( p32bitVram + XDir ) = *cast(uint*) Mix;
} *( LastEndWriteAddr + xPosEnd + yPosEnd * VramPitch ) = clrLine;
return;
}
ErrorAdj = cast(uint) ( (cast(ulong) DeltaY << 32) / cast(ulong) DeltaX);

while (--DeltaX) {
ErrorAccTemp = ErrorAcc;

*cast(uint*) Bg = ((ErrorAcc += ErrorAdj) <= ErrorAccTemp ? * ( p32bitVram += XDir + VramPitch ) : * ( p32bitVram += XDir ) );

Weighting = ErrorAcc >> 24;

grayb = ( (cast(uint) Bg[2] << 2) + cast(uint) Bg[1] * 5 +cast(uint) Bg[0] );

WeightingShrink = (grayl >= grayb ? Weighting ^ 0xFF : Weighting) / 255.0;

Mix[2] = ( Bg[2] > Line[2] ? ( cast(ubyte)( WeightingShrink * ( Bg[2] - Line[2] ) + Line[2] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[2] - Bg[2] ) + Bg[2] ) ) );
Mix[1] = ( Bg[1] > Line[1] ? ( cast(ubyte)( WeightingShrink * ( Bg[1] - Line[1] ) + Line[1] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[1] - Bg[1] ) + Bg[1] ) ) );
Mix[0] = ( Bg[0] > Line[0] ? ( cast(ubyte)( WeightingShrink * ( Bg[0] - Line[0] ) + Line[0] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[0] - Bg[0] ) + Bg[0] ) ) );

*( p32bitVram ) = *cast(uint*) Mix;
*cast(uint*) Bg = *( p32bitVram + VramPitch );

grayb = ( ( cast(uint) Bg[2] << 2 ) + cast(uint) Bg[1] * 5 + cast(uint) Bg[0] );

WeightingShrink = cast (double)(grayl < grayb ? Weighting ^ 0xFF : Weighting) / 255.0;

Mix[2] = ( Bg[2] > Line[2] ? ( cast(ubyte)( WeightingShrink * ( Bg[2] - Line[2] ) + Line[2] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[2] - Bg[2] ) + Bg[2] ) ) );
Mix[1] = ( Bg[1] > Line[1] ? ( cast(ubyte)( WeightingShrink * ( Bg[1] - Line[1] ) + Line[1] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[1] - Bg[1] ) + Bg[1] ) ) );
Mix[0] = ( Bg[0] > Line[0] ? ( cast(ubyte)( WeightingShrink * ( Bg[0] - Line[0] ) + Line[0] ) ) : ( cast(ubyte)( WeightingShrink * ( Line[0] - Bg[0] ) + Bg[0] ) ) );

*( p32bitVram + VramPitch ) = *cast(uint*) Mix;
} *( LastEndWriteAddr + xPosEnd + yPosEnd * VramPitch ) = clrLine;
}

BR直线汇编代码
void _NcLine ( int x0, int y0, 
int x1, int y1, uint p32BitVram, int pitch, uint color ) {

asm {
naked ; // use naked asm mode
pushad ; // save old frame

mov ECX, 36[ESP] ; // ECX <- x0
mov EDX, 40[ESP] ; // EDX <- y0

mov EDI, 44[ESP] ; // EDI <- x1
mov ESI, 48[ESP] ; // ESI <- y1

cmp ECX, EDI ; // x0 < x1 ?
setl AL ; // Y ? AL = 1 : AL = 0

shl EAX, 31 ; // left shift save old flags
cmp EDX, ESI ; // y0 < y1 ?

setl AL ; // Y ? AL = 1 : AL = 0
rol EAX, 1 ; // bit0: X bit1: Y

lea EAX, gtIndex[EAX*8] ;
jmp EAX ;

align 16 ;
gtIndex:
xchg EDI, ECX ;
xchg ESI, EDX ;

jmp R2 ;
xor EAX, EAX ;

xchg EDI, ECX ;
xchg ESI, EDX ;

jmp tempTable ;
xor EAX, EAX ;
tempTable:
jmp R1 ;
xchg EDI, ECX ;

inc EAX ;

R2: // x0 < x1/y0 < y0

sub EDI, ECX ; // RV - X
sub ESI, EDX ; // RV - Y

xor EAX, EAX ; // clear

cmp ESI, EDI ; // RV - Y > RV - X ?
seta AL ; // is > 0 ? AL = 1 : AL = 0

ror EAX, 1 ; // save old frame ror op not affect z bit
setz AL ; // is Equal ?

lea EAX, R2gtIndex[EAX*8] ; // table
jmp EAX ;

align 16 ;

R2gtIndex: /// r2 TABLE
jmp R2NearX ;
jmp R2NearY ;
inc EDX ;
jmp R2NearY ;
imul ECX, EAX ;

R2Align: // 45 du ^

mov EAX, 56[ESP] ; //pitch
imul ECX, EAX ; //- N pitch * tStartY

add EAX, 4 ;// ouy
lea ECX, [ECX+EDX*4] ; //init pVram comp

mov EDX, 60[ESP] ; //EDX = color
add ECX, 52[ESP] ; //pVram Pos + RVA

imul EDI, EAX ; //- N rv - y * ouy = start to end 's RVA total ...

neg EDI; //- N neg opr
sub ECX, EDI ; //init first write ...

align 16 ;

R2Align_main_loop:

mov [ECX+EDI], EDX ; //maybe have agi clash
lea ESP, [ESP] ;

add EDI, EAX ; // emmm ... maybe this is not fast :(
jne R2Align_main_loop ; // when write vram finish EDI is zero

mov [ECX+EDI], EDX ; // last write vram
popad ;
ret ;

R2NearX:

movd XMM7, ESP ;

mov EAX, 56[ESP] ;

neg EDI ; // dx

imul EDX, EAX ; //

lea EBX, [EDX+ECX*4] ; // RVA Vram Pos
add ESI, ESI ;

add EBX, 52[ESP] ; // p32BitVram + RVA Vram Pos
lea EDX, 4[EAX] ; //

lea ECX, [ESI+EDI] ; // ECX = error
mov ESP, 60[ESP] ; // ESP = color

lea EBP, [ECX+EDI] ; //
test ECX, ECX ;

jge R2NearX_Ex ;

align 16 ;

R2NearX_main_loop:

mov [EBX], ESP ;
jc R2NearX_RP ;

add EBX, 4 ;
add ECX, ESI ;

inc EDI ;
jne R2NearX_main_loop ;
jmp R2NearXRet ;

R2NearX_RP:

add EBX, EDX ;
add ECX, EBP ;

inc EDI ;
jne R2NearX_main_loop ;

R2NearXRet:

mov [EBX], ESP ;
movd ESP, XMM7 ;
popad ;
ret ;

R2NearX_Ex:

mov [EBX], ESP ;

add EBX, EDX ;
add ECX, EBP ;

inc EDI ;
jne R2NearX_main_loop ;
jmp R2NearXRet ;
R2NearY:

movd XMM0, ESP ;

mov EAX, 56[ESP] ; // pitch

neg ESI ; // dy

imul EDX, EAX ; // - N pitch * tStartY ( EDX )

lea EBX, [EDX+ECX*4] ; // init pVram comp
add EDI, EDI ; // dx2

add EBX, 52[ESP] ; // pVram Pos + RVA
lea EDX, 4[EAX] ; // EBP = ruy

lea ECX, [EDI+ESI] ; // error
mov ESP, 60[ESP] ;

lea EBP, [ECX+ESI] ; // EBP = ogh
test ECX, ECX ;

jge R2NearY_RP_Ex ;

align 16 ;

/*
R2NearY_main_loop:

mov [EBX], ESP ; // - U
jc R2NearY_RP ; // - V

add EBX, EAX ; // - U
add ECX, EDI ; // - V

inc ESI ; // - U
jne R2NearY_main_loop ; // - V

mov [EBX], ESP ; // - U
jmp R2NearY_ret ; // - V

R2NearY_RP:

add EBX, EDX ; //
add ECX, EBP ;

inc ESI ;
jne R2NearY_main_loop ;
*/
R2NearY_main_loop:

mov [EBX], ESP ; // - U
jnc R2NearY_no_repair ; // - V

R2NearY_RP:

add EBX, EDX ; //
add ECX, EBP ; //

inc ESI ; //
jne R2NearY_main_loop ; //
jmp R2NearY_ret ; // - V

R2NearY_no_repair:

add EBX, EAX ; // - U
add ECX, EDI ; // - V

inc ESI ; // - U
jne R2NearY_main_loop ; // - V

R2NearY_ret:

mov [EBX], ESP ;
movd ESP, XMM7 ;
popad ;
ret ;

R2NearY_RP_Ex:

mov [EBX], ESP ;
add EBX, EDX ;

add ECX, EBP ;
inc ESI ;
jne R2NearY_main_loop ;
jmp R2NearY_ret;

R1:// ----- x0 > x1/y0 <= y1

sub ECX, EDI ; //--- RV - X
sub ESI, EDX ; // RV - Y

xor EAX, EAX ; //
cmp ECX, ESI ; // RV - Y > RV - X ?

setl AL ; // 1 > 0 <=
ror EAX, 1 ;

setz AL ;
rol EAX, 1 ;

lea EAX, R1gtIndex[EAX*8];
jmp EAX ;

align 16 ;

R1gtIndex: /// r1 TABLE

jmp R1NearX; // 1
jmp R1NearY;
inc EDX;
jmp R1NearY; // 2
imul ECX, EAX;

R1Align:

mov EAX, 56[ESP] ; //pitch
add EDX, ESI ;

imul EDI, EAX ; //- N pitch * tStartY
sub EAX, 4 ; //ouy

lea EDI, [EDI+EDX*4] ; //init pVram comp

mov EDX, 60[ESP] ; //EDX = color
add EDI, 52[ESP] ; //pVram Pos + RVA

imul ESI, EAX ; //- N rv - y * ouy = start to end 's RVA total ...

neg ESI; //- N neg opr
sub EDI, ESI ;// init first write ...

align 16 ;

R1Align_main_loop:

mov [EDI+ESI], EDX ; // maybe have agi clash
lea ESP, [ESP] ;

add ESI, EAX ; // emmm ... maybe this is not fast :(
jne R1Align_main_loop ; // when write vram finish EDI is zero

popad ;
ret ;

R1NearX:

movd XMM7, ESP ;

mov EAX, 56[ESP] ; // pitch
add EDI, ECX ;

imul EDX, EAX ; //- N pitch * tStartY ( EDX )
neg ECX ; // dx

lea EBX, [EDX+EDI*4] ; //init pVram comp
add ESI, ESI ;// dy2

add EBX, 52[ESP] ; //pVram Pos + RVA
lea EDI, [EAX-4] ; //EDI = ruy

lea EBP, [ESI+ECX] ; //error
mov ESP, 60[ESP] ;

lea EDX, [EBP+ECX] ; //EDX = ogh
test EBP, EBP ;

jge R1NearX_RP_Ex ;

align 16 ;

R1NearX_main_loop:

mov [EBX], ESP;
jc R1NearX_repair;

sub EBX, 4;
add EBP, ESI;

inc ECX;
jne R1NearX_main_loop;
jmp R1NearX_ret;

R1NearX_repair:

add EBX, EDI;
add EBP, EDX;

inc ECX ;
jne R1NearX_main_loop ;

R1NearX_ret:

mov [EBX], ESP;
movd ESP, XMM7 ;
popad ;
ret ;

R1NearX_RP_Ex:

mov [EBX], ESP;

add EBX, EDI;
add EBP, EDX;

inc ECX ;
jne R1NearX_main_loop;
jmp R1NearX_ret ;

R1NearY:

movd XMM7, ESP;

mov EAX, 56[ESP] ; //pitch

neg ESI ;// dy .

imul EDX, EAX ; //- N pitch * tStartY ( EDX )

add EDI, ECX;
lea EBX, [EDX+EDI*4] ; //init pVram comp

add ECX, ECX ; //dx2
add EBX, 52[ESP] ; //pVram Pos + RVA

lea EDI, [EAX-4] ; //EDI = ruy
lea EBP, [ESI+ECX] ; //error

mov ESP, 60[ESP] ; //color
lea EDX, [EBP+ESI] ; //EDX = ogh

test EBP, EBP;
jge R1NearY_RP_Ex ;

align 16 ;

R1NearY_main_loop:

mov [EBX], ESP;
jc R1NearY_repair;

add EBX, EAX;
add EBP, ECX;

inc ESI;
jne R1NearY_main_loop;
jmp R1NearY_ret;

R1NearY_repair:

add EBX, EDI;
add EBP, EDX;

inc ESI ;
jne R1NearY_main_loop;

R1NearY_ret:

mov [EBX], ESP;
movd ESP, XMM7 ;
popad ;
ret ;

R1NearY_RP_Ex:

mov [EBX], ESP;

add EBX, EDI;
add EBP, EDX;

inc ESI ;
jne R1NearY_main_loop ;
}
}

你可能感兴趣的:(算法)