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 ;
		}
}

猜你喜欢

转载自xuling1993728.iteye.com/blog/2199578