; Numérise un bord de (X1,Y1) en (X2,Y2), ce qui n'inclut pas ; le point en (X2,Y2). Si SkipFirst == 1, le point en (X1,Y1) n'est pas ; affiché; il l'est, si SkipFirst == 0. Pour chaque ligne d'affichage, le pixel ; le plus proche du bord parcouru qui n'est pas à sa gauche ; est choisi. Utilise une approche "tout entier" pour la vitesse & la précision. ; Appelable depuis C near comme suit: ; void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart, ; int SkipFirst, struct HLine **EdgePointPtr); ; Les bords ne doivent pas aller de bas en haut; c'est-à-dire, Y1 doit être <= Y2. ; Met à jour le pointeur pointé sur EdgePointPtr pour pointer sur la prochaine ; entrée libre dans le tableau de structures HLine. ; ; Lié avec L21-1.C, L21-3.C, et L22-3.ASM en modèle Small. ; Testé avec TASM 4.0 et Borland C++ 4.02 par Jim Mischel 12/16/94. ; HLine struc XStart dw ? ;coordonnée X du pixel le plus ; à gauche dans la ligne ;d'affichage XEnd dw ? ;coordonnée X du pixel le plus ; à droite dans la ligne ;d'affichage HLine ends Parms struc dw 2 dup(?) ;adresse de retour & BP ;empilés X1 dw ? ;coordonnée X du début du bord Y1 dw ? ;coordonnée Y du début du bord X2 dw ? ;coordonnée X de la fin du bord Y2 dw ? ;coordonnée Y de la fin du bord SetXStart dw ? ;1 pour positionner le champ ;XStart de ; chaque structure HLine, 0 pour XEnd SkipFirst dw ? ;1 pour sauter le parcours du ;premier point ;du bord, 0 pour parcourir le premier point EdgePointPtr dw ? ;pointe sur un pointeur du tableau ; des structures HLine dans lequel ; stocker les coordonnées ;X parcourues Parms ends ;Offsets depuis BP dans la stack frame des variables locales. AdvanceAmt equ -2 Height equ -4 LOCAL_SIZE equ 4 ;taille totale des variables locales .model small .code public _ScanEdge align 2 _ScanEdge proc push bp ;préserve la stack frame ;de l'appelant mov bp,sp ;pointe sur notre stack ; frame sub sp,LOCAL_SIZE ;alloue de ;l'espace aux variables ;locales push si ;préserve les variables ;registre de l'appelant push di mov di,[bp+EdgePointPtr] mov di,[di] ;pointe sur le tableau ; HLine cmp [bp+SetXStart],1 ;positionne ;le champ XStart field de chaque ; structure HLine? jz HLinePtrSet ;oui, DI pointe ;sur le premier XStart add di,XEnd ;non, pointe sur le ;champ XEnd fde la ;première structure HLine HLinePtrSet: mov bx,[bp+Y2] sub bx,[bp+Y1] ;hauteur du bord jle ToScanEdgeExit ;évite les bords ; de longueur 0 & horizontaux mov [bp+Height],bx ;Hauteur = Y2 ;- Y1 sub cx,cx ;suppose que ErrorTerm ; commence à 0 (vrai si ; nous nous déplaçons à droite ;en affichant) mov dx,1 ;suppose que AdvanceAmt ; = 1 (déplacement vers ;la droite) mov ax,[bp+X2] sub ax,[bp+X1] ;DeltaX = X2 - X1 jz IsVertical ;c'est un bord ;vertical->cas ;particulier jns SetAdvanceAmt ;DeltaX >= 0 mov cx,1 ;DeltaX < 0 (déplace à ;gauche en affichant) sub cx,bx ;ErrorTerm = -Height + ; 1 neg dx ;AdvanceAmt = -1 (déplace- ;ment à gauche) neg ax ;Largeur = abs(DeltaX) SetAdvanceAmt: mov [bp+AdvanceAmt],dx ; Détermine si le bord est diagonal, X principal(plus horizontal), ; ou Y principal(plus vertical) et traite selon. cmp ax,bx ;si Width==Height, ;c'est un bord diagonal jz IsDiagonal ;c'est un bord ;diagonal->cas particulier jb YMajor ;C'est un bord Y ;principal(plus vertical) ;C'est un bord X principal ;(plus horizontal) sub dx,dx ;prépare DX:AX (Width) ; pour la division div bx ;Width/Height ;DX = terme d'erreur avance par ; ligne d'affichage mov si,ax ;SI = nombre minimum ;de pixels à avancer de X ; sur chaque ligne d'affichage test [bp+AdvanceAmt],8000h ;déplace- ;ment gauche ou droite? neg si ;gauche, rend négative la ;distance pour avancer ; sur chaque ligne d'affichage XMajorAdvanceAmtSet: ; mov ax,[bp+X1] ;coordonnée X de départ cmp [bp+SkipFirst],1 ;saute le premier ;point? jz XMajorSkipEntry ;oui XMajorLoop: mov [di],ax ;stocke la valeur courante ; de X add di,size HLine ;pointe sur la ; prochaine structure HLine XMajorSkipEntry: add ax,si ;paramètre X pour la ;prochaine ligne d'affichage add cx,dx ;avance le terme ;d'erreur jle XMajorNoAdvance ;pas le temps ;d'avancer la coordonnée X ; de un add ax,[bp+AdvanceAmt];avance la ;coordonnée X de un sub cx,[bp+Height] ;réajuste le terme ;d'erreur XMajorNoAdvance: dec bx ;décompte cette ligne ;d'affichage jnz XMajorLoop jmp ScanEdgeDone align 2 ToScanEdgeExit: jmp ScanEdgeExit align 2 IsVertical: mov ax,[bp+X1] ;coordonnée X de départ ; (et seulement) sub bx,[bp+SkipFirst] ;compte la boucle ;= Height - SkipFirst jz ScanEdgeExit ;ne reste plus de lignes ; après avoir sauté la première VerticalLoop: mov [di],ax ;stocke la valeur courante ; de X add di,size HLine ;pointe sur la ; prochaine structure HLine dec bx ;décompte cette ligne ;d'affichage jmp ScanEdgeDone align 2 IsDiagonal: mov ax,[bp+X1] ;coordonnée X de ;départ cmp [bp+SkipFirst],1 ;saute le premier ;point? jz DiagonalSkipEntry ;oui DiagonalLoop: mov [di],ax ;stocke la valeur ; courante de X add di,size HLine ;pointe sur la ;prochaine structure HLine DiagonalSkipEntry: add ax,dx ;avance la coordonnée X dec bx ;décompte cette ligne ;d'affichage jnz DiagonalLoop jmp ScanEdgeDone align 2 YMajor: push bp ;préserve le pointeur de la ;stack frame mov si,[bp+X1] ;coordonnée X de départ cmp [bp+SkipFirst],1 ;saute le premier ;point? mov bp,bx ;stocke Height dans BP pour ;le calcul du terme d'erreur jz YMajorSkipEntry ;oui, saute le premier ; point YMajorLoop: mov [di],si ;stocke la valeur courante ; de X add di,size HLine ;pointe sur la ;prochaine structure ;HLine YMajorSkipEntry: add cx,ax ;avance le terme ;d'erreur jle YMajorNoAdvance ;pas le temps ; d'avancer la ;coordonnée X add si,dx ;avance la coordonnée X sub cx,bp ;réajuste le terme ;d'erreur YMajorNoAdvance: dec bx ;décompte cette ligne ;d'affichage jnz YMajorLoop pop bp ;restaure le pointeur de la ; stack frame ScanEdgeDone: cmp [bp+SetXStart],1 ;travaillons-nous ;avec le champ XStart? jz UpdateHLinePtr ;oui, DI pointe sur ;le prochain XStart sub di,XEnd ;non, re-pointe sur le ; champ XStart UpdateHLinePtr: mov bx,[bp+EdgePointPtr] ;pointe sur ; le pointeur du tableau ;HLine mov [bx],di ;met à jour le pointeur ; du tableau HLine de l'appelant ScanEdgeExit: pop di ;restaure les variables ;registre de l'appelant pop si mov sp,bp ;désalloue les variables ;locales pop bp ;restaure la stack frame de ; l'appelant ret _ScanEdge endp end