;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = DRAWLINE.ASM
;*
;* DESCRIPTIVE NAME = Polyline drawing device driver.
;*
;*
;* VERSION      V2.0
;*
;* DATE         10/19/87
;*
;* DESCRIPTION  This file contains functions related to drawing lines
;*
;* FUNCTIONS    DrawLinesInPath
;*              DrawLinesCorrelate
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   10/19/87                     Written by Kent Settle
;*   06/20/88  @Vx.xBXG00         Bob Grudem [bobgru] Implemented the "max" metric
;*                                for line styling.
;*   10/18/91                     Cliff Levesque [cliffl] Cleanup and convert
;*                                to 386 and above flat model, protected mode
;*                                32 bit operation.
;*   11/26/92                     John Batty. Added DCAF changes.
;*
;*****************************************************************************/

        .386

        OPTION  OLDSTRUCTS

        .xlist

INCL_DDIPATHS           equ     1
INCL_GRE_LINES          equ     1
INCL_DDICOMFLAGS        equ     1
INCL_GPICORRELATION     equ     1
INCL_GPIPRIMITIVES      equ     1
INCL_GPIERRORS          equ     1
DINCL_ROPS              equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1
OS2P_DEFD               equ     1

        include pmgre.inc
        include driver.inc
        include extern.inc
        include protos.inc
        include polyline.inc                     ; polyline equates file

        .list

        .MODEL FLAT

        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT

        .DATA

        .CODE

;/***************************************************************************
;*
;* FUNCTION NAME = DrawLinesInPath
;*
;* DESCRIPTION   = Draws a given number of lines from a giwen path structure.
;*
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX,FLAGS.
;*
;*                 Registers Preserved:
;*                       EDI,ESI,EBP
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1  if no correlation hit
;*                 EAX = 2  if correlation hit
;* RETURN-ERROR  = EAX = 0  if polylines not drawn
;*
;**************************************************************************/

ALIGN 4
DrawLinesInPath PROC    SYSCALL USES esi edi EBX, hdc:DWORD, lpph:DWORD,
                                                  lpcvFirst:DWORD, icvCount:DWORD,
                                                  hddc:DWORD, FunN:DWORD

        LOCAL   returnvalue:DWORD,
                dwStyleCounter:DWORD,
                Flags:DWORD,
                Count:DWORD,
                Points:DWORD,
                npddc:DWORD
        LOCAL   dwStyleMask:DWORD,
                npfnUnSetup:DWORD,
                CurLineColor:DWORD,
                DrawModeIndex:DWORD,
                cPlanes:DWORD
        LOCAL   cbNextPlane:DWORD,
                dwBitmapROP:DWORD,
                dwStyleStepHorz:DWORD,
                dwStyleStepVert:DWORD,
                dwStyleStepDiag:DWORD,
                dwStyleStepHorzTmp:DWORD,
                dwStyleStepVertTmp:DWORD
        LOCAL   offNextLine:DWORD,
                cbScanSize:DWORD,
                cbHugeScanWrap:DWORD,
                cySurface:DWORD
        LOCAL   cScansPerSegment:DWORD,
                pSurfaceStart:DWORD,
                anpfnRunRoutines:DWORD,
                LineStyle:DWORD,
                npfnPassSetup:DWORD,
                cPasses:DWORD,
                lsg:LINESEGMENT
        LOCAL   dwStyleStepRun:DWORD,
                dwStyleStepSide:DWORD,
                dwActiveStyleCounter:DWORD,
                dwActiveStyleMask:DWORD,
                yA:DWORD,
                cScans:DWORD,
                cA:DWORD,
                cB:DWORD,
                cm:DWORD
        LOCAL   npfnRunRoutine:DWORD,
                iWhichDDA:DWORD,
                dwError:DWORD,
                dwFracS:DWORD,
                dwRotBitMask:DWORD,
                cbScanAddressDelta:DWORD
        LOCAL   cbSideStepAddressDelta:DWORD,
                cbHugeScanDelta:DWORD,
                selHugeDelta:DWORD,
                dwScan:DWORD,
                pSurfaceAddress:DWORD
        LOCAL   cTmpScans:DWORD,
                dwTmpError:DWORD,
                dwTmpScan:DWORD,
                dwTmpRotBitMask:DWORD,
                dwTmpActiveStyleCounter:DWORD,
                dwTmpActiveStyleMask:DWORD,
                cTmpPasses:DWORD,
                TmpCurLineColor:DWORD

        DebugMsg <DrawLinesInPath CLIFFL>

        mov     Flags,0
        mov     returnvalue,1           ; assume all OK

;/*
;** This call only makes sense with the device locked, check it out!
;*/

ifdef FIREWALLS

        INVOKE  check_sem
        or      eax,eax
        jz      @F

        rip     text,<DrawLinesInPath called without LockDevice>

@@:

endif
        INSURE_VISREGIONNOTIFY

;/*
;** Make sure the system colors and IPC are up to date.  If the system
;** colors did change, the IPC will have to also be realized.
;*/

        mov     esi,hddc                ; ESI --> DDC

        ASSUME  esi:PTR DDC

        mov     eax,ddcInit.ddc_iSysClr

        cmp     eax,[esi].ddc_iSysClr
        jne     dlip_need_sys_colors
        test    [esi].ddc_la.la_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV
        jz      dlip_have_valid_ipc
        jmp     dlip_get_new_ipc
ALIGN 4

dlip_need_sys_colors:

        INVOKE  PropagateSysClrChange

dlip_get_new_ipc:

        lea     ebx,[esi].ddc_la.la_ba
        call    MakeColorsValid
        jns     dlip_have_valid_ipc
        jmp     dlip_error_exit         ;Error logged by MakeBrushValid
ALIGN 4

;/*
;** Some error handlers in here
;*/

dlip_no_surface:

        mov     eax,PMERR_BITMAP_NOT_SELECTED
        jmp     dlip_log_error
ALIGN 4

dlip_bad_count:

        mov     eax,PMERR_INV_LENGTH_OR_COUNT

dlip_log_error:

        save_error_code

dlip_error_exit:

        xor     eax,eax                 ; indicate error
        jmp     drawline_exit
ALIGN 4


dlip_good_exit_relay:

        jmp     drawline_good_exit
ALIGN 4

;/*
;** Make sure we have a surface and valid counts
;*/

dlip_have_valid_ipc:

        test    [esi].ddc_fb,DDC_PRESENT
        jz      dlip_no_surface
        mov     ecx,icvCount
        jecxz   dlip_good_exit_relay

;/*
;** accumulate bounds
;*/

        mov     edi,FunN        ; EDI = Command

ifdef FIREWALLS

        test    edi,COM_BOUND+COM_ALT_BOUND
        jz      @F

        rip     text,<Bounds should not be set>

@@:

endif

ifdef DCAF                                                           ;          
;/*                                                                  ;          
;** Although there is no need to do the GPI or USER bounds for       ;          
;** this primitive (because this can only be called as a result      ;          
;** of a engine simulation which is responsible for accumulating     ;          
;** the bounds anyway), we must always do SCREEN bounds.             ;          
;*/                                                                  ;          
        test    edi,COM_SCR_BOUND                                    ;          
        jz      bounds_considered                                    ;          
;/*                                                                  ;          
;** Fortunately the PATH definition which we are passed holds        ;          
;** a bounding rectangle that we can access.                         ;          
;*/                                                                  ;          
        pushem  eax,ebx,ecx,edx                                      ;          
                                                                     ;          
        mov     ebx,lpph                                             ;          
;/*                                                                  ;          
;** Don't know where the path structure is defined (is it?),         ;          
;** so pick up the bounding rectangle from the same place            ;          
;** as the cursor exclusion code that appears later in this file.    ;          
;*/                                                                  ;          
        ASSUME  ebx:PTR RECTL                                        ;          
        mov     eax,[ebx].rcl_xLeft     ; EAX = left (inclusive)     ;          
        mov     ecx,[ebx].rcl_xRight    ; ECX = right (inclusive)    ;          
        mov     edx,[ebx].rcl_yTop      ; EDX = top (inclusive)      ;          
        mov     ebx,[ebx].rcl_yBottom   ; EBX = bottom (inclusive)   ;          
;/*                                                                  ;          
;** The bounding rectangle we have just picked up is not clipped -   ;          
;** thus it may include off screen values.                           ;          
;** InnerAccumulateBounds will detect that this call is from         ;          
;** DrawLinesInPath (the function number is in the lower 16 bits     ;          
;** of edi) and clip the bounding rectangle.                         ;          
;**                                                                  ;          
;*/                                                                  ;          
        call    InnerAccumulateBounds   ; esi->DDC, edi = FunN       ;          
                                                                     ;          
        popem   eax,ebx,ecx,edx                                      ;          
bounds_considered:                                                   ;          
endif ; DCAF                                                         ;          
                                                                     ;          

;/*
;** compute correlation
;*/

        test    edi,COM_CORRELATE
        jz      correlate_done
        mov     edi,lpcvFirst           ; EDI = curves
        INVOKE  DrawLinesCorrelate,ecx
        mov     returnvalue,eax

correlate_done:

;/*
;** draw the lines
;*/

        mov     cl,[esi].ddc_fb
        and     cl,DDC_VISIBLE

        .errnz  DDC_VISIBLE - COM_DRAW SHR 16

        test    byte ptr FunN[2],cl
        jz      drawing_all_done

;/*
;** exclude the pointer if the device
;*/

        test    [esi].ddc_fb,DDC_DEVICE
        jz      exclusion_done
        mov     ebx,lpph

        ASSUME  ebx:PTR RECTL

        mov     ecx,[ebx].rcl_xLeft     ; CX = left (inclusive)
        mov     edi,[ebx].rcl_yBottom   ; DI = bottom (inclusive)
        mov     esi,[ebx].rcl_xRight    ; SI = right (inclusive)
        mov     edx,[ebx].rcl_yTop      ; DX = top (inclusive)
        sub     edx,SCREEN_CY           ; SEL 1-27-92
        inc     edx                     ; SEL 1-27-92
        neg     edx
        sub     edi,SCREEN_CY           ; SEL 1-27-92
        inc     edi                     ; SEL 1-27-92
        neg     edi
        call    far_exclude             ; (destroys ES)

exclusion_done:

;/*
;** initialize according to the physical device type
;*/

        mov     edi,hddc
        call    polyline_init

setup_drawlines:

        mov     eax,icvCount
        mov     Count,eax
        mov     eax,lpcvFirst
        mov     Points,eax

;/*
;** loop through all curves
;*/

drawlines_loop:

        mov     edi,Points

        ASSUME  edi:PTR LINE

        mov     eax,[edi].ln_pcvNext
        mov     Points,eax

ifdef FIREWALLS

        cmp     [edi].ln_bIdent,CURVE_IDENTIFIER
        jz      @F

        rip     text,<Curve identifier invalid>

@@:

endif

;/*
;*/

        cmp     [edi].ln_bType,LINE_IDENTIFIER
        jnz     drawlines_next

;/*
;** normalize the line
;*/

        xor     esi,esi                         ; ESI = flags

        mov     eax,[edi].ln_ptlA.ptl_x                ; (EAX,EBX) = point 1
        mov     ebx,[edi].ln_ptlA.ptl_y
        mov     ecx,[edi].ln_ptlC.ptl_x                ; (ECX,EDX) = point 2
        mov     edx,[edi].ln_ptlC.ptl_y

;/*
;** make sure we go left to right
;*/

        cmp     eax,ecx
        jle     is_left_to_right
        xchg    eax,ecx
        xchg    ebx,edx
        or      esi,LF_LEFT_XCHG

is_left_to_right:

;/*
;** record the start position (so we can calculate the surface address)
;*/

        mov     lsg.lsg_xStart,eax
        mov     lsg.lsg_yStart,ebx

;/*
;** normalize coordinates relative to xStart and yStart
;*/

        sub     ecx,eax
        sub     edx,ebx
        jge     y_be_unsigned
        neg     edx
        or      esi,LF_Y_FLIP + LF_VERTICAL_FLIP

y_be_unsigned:

;/*
;** get x-major
;*/

        cmp     edx,ecx
        jbe     we_be_x_major
        xchg    edx,ecx
        or      esi,LF_XY_XCHG

we_be_x_major:

;/*
;** remember the normalized line
;*/

        mov     lsg.lsg_cdx,ecx
        mov     lsg.lsg_cdy,edx

;/*
;** Compute the clip range from the POINTFXs.  Handle the y-major case.
;*/

        test    esi,LF_XY_XCHG           ; test for y-major
        jz      ptfx_x_major

        neg     ebx                     ; get relative to the start y!
        mov     edx,ebx
        mov     eax,[edi].ln_ptfxA.ptfx_y         ; FIXED y1
        sar     eax,16                            ; trash the fractional part
        adc     ebx,eax                           ; carry rounds up if >= 0.5
        mov     eax,[edi].ln_ptfxC.ptfx_y         ; FIXED y2
        sar     eax,16                            ; trash the fractional part
        adc     edx,eax

;/*
;** do Y flip
;*/

        test    esi,LF_Y_FLIP
        jz      do_left_flips
        neg     ebx
        neg     edx
        jmp     do_left_flips
ALIGN 4

;/*
;** handle the x-major case
;*/

ptfx_x_major:

        neg     eax
        mov     ebx,eax
        mov     edx,eax
        mov     eax,[edi].ln_ptfxA.ptfx_x         ; FIXED x1
        sar     eax,16                            ; trash the fractional part
        adc     ebx,eax                           ; carry rounds up if >= 0.5
        mov     eax,[edi].ln_ptfxC.ptfx_x         ; FIXED x2
        sar     eax,16                            ; trash the fractional part
        adc     edx,eax

;/*
;** do left flips
;*/

do_left_flips:
        test    esi,LF_LEFT_XCHG
        jz      @F
        xchg    ebx,edx
@@:

;/*
;** clip off the first pel, if needed
;*/

        test    [edi].ln_fl,CURVE_DO_FIRST_PEL
        jnz     all_clipping_done
        test    esi,LF_LEFT_XCHG
        jnz     is_left_exchanged
        or      ebx,ebx
        jnz     all_clipping_done
        inc     ebx
        jmp     all_clipping_done
ALIGN 4

is_left_exchanged:

        mov     eax,lsg.lsg_cdx         ; AX = major extent
        cmp     edx,eax
        jb      all_clipping_done
        dec     eax
        mov     edx,eax
        inc     eax
        jnz     all_clipping_done       ; watch out for the zero length line!
        xor     edx,edx         
        mov     ebx,1

all_clipping_done:

;/*
;** remember the clip interval
;*/

        mov     lsg.lsg_xA,ebx
        mov     lsg.lsg_xB,edx

;/*
;** do styling and half flip
;*/

        cmp     BYTE PTR LineStyle,LINETYPE_SOLID - 1
        jz      ignore_styles

;**@Vx.xBXG00  start of max metric changes (bobgru)-----------------

        cmp     BYTE PTR LineStyle,LINETYPE_ALTERNATE - 1
        jnz     determine_major_styling

        mov     eax,dwStyleStepHorz
        mov     ecx,eax                 ;wStyleStepVert = wStyleStepHorz
        mov     dwStyleStepDiag,eax     ;wStyleStepDiag =       "
        jmp     store_style_steps
ALIGN 4

;/*
;** Determine whether line is styled as x or y major.
;** If LF_XY_XCHG is true, then DI will be delta_y, but
;** we want it to be delta_x, so swap SI and DI.
;*/

determine_major_styling:

        mov     eax,dwStyleStepHorz
        mov     ebx,dwStyleStepVert
        test    esi,LF_XY_XCHG
        jz      @F
        xchg    eax,ebx
@@:
        mov     dwStyleStepHorzTmp,eax  ; really is major step
        mov     dwStyleStepVertTmp,ebx  ; really is minor step

        mul     lsg.lsg_cdx             ; DX:AX = major_step * delta_major
        xchg    eax,ebx                 ; 
        mov     ecx,edx                 ; save all 32 bits
        mul     lsg.lsg_cdy             ; DX:AX = minor step * delta_minor
        cmp     edx,ecx
        jb      styled_as_expected
        ja      styled_as_opposite
        cmp     eax,ebx
        ja      styled_as_opposite

styled_as_expected:

        mov     dwStyleStepVertTmp,0    ; set minor step to 0
        jmp     set_diag_style_step
ALIGN 4

styled_as_opposite:

        mov     dwStyleStepHorzTmp,0    ; set major step to 0

set_diag_style_step:

        mov     eax,dwStyleStepHorzTmp  ; take major step
        mov     ecx,eax                 ; side step = major step +
        add     ecx,dwStyleStepVertTmp  ;             minor step

;/*
;** Determine major and side style steps.
;*/

store_style_steps:

        mov     dwStyleStepRun,eax
        mov     dwStyleStepDiag,eax
        mov     dwStyleStepSide,ecx

;**@Vx.xBXG00----------end of max metric changes (bobgru)-----------------

;/*
;** compute the change in style
;*/

        mov     ebx,lsg.lsg_cdx         ; change = RunStep * (major - minor)
        sub     ebx,lsg.lsg_cdy         ;        + SideStep * minor
        mul     ebx
        xchg    eax,ecx
        mul     lsg.lsg_cdy
        add     eax,ecx                 ; AX = style change
        mov     ebx,[edi].ln_flStyle    ; BX = style at start
        add     eax,ebx                 ; AX = style at finish

;/*
;** reverse the style if we've exchanged left for right
;*/

        mov     edx,dwStyleMask
        test    esi,LF_LEFT_XCHG
        jz      @F
        mov     ebx,eax
        not     ebx                     ; BX = style count to use
        mov     dl,dh                   ; DL = style mask to use
@@:     mov     BYTE PTR dwActiveStyleCounter,bl
        mov     cl,bh
        and     cl,7
        rol     dl,cl
        mov     BYTE PTR dwActiveStyleMask,dl

;/*
;** do the styling version of a half-flip
;*/

        mov     ecx,lsg.lsg_cdx
        mov     edx,lsg.lsg_cdy
        mov     eax,edx
        add     eax,eax
        ;SEL 1-27-92: This isn't needed
        ;jc     flip_it_style           ; 2dy > dx -- half flip needed
        cmp     eax,ecx
        jbe     @F                      ; 2dy <= dx -- no half flip needed

flip_it_style:

        sub     edx,ecx
        neg     edx
        xor     esi,LF_HALF_FLIP + LF_VERTICAL_FLIP

;/*
;** exchange the style steps
;*/

        mov     eax,dwStyleStepRun
        xchg    eax,dwStyleStepSide
        mov     dwStyleStepRun,eax
        mov     dwStyleStepDiag,eax
@@:
        jmp     half_flips_done
ALIGN 4

;/*
;** do half flip for the non-styled case
;*/

ignore_styles:

        mov     ecx,lsg.lsg_cdx
        mov     edx,lsg.lsg_cdy
        mov     eax,edx
        add     eax,eax                 ; 
        cmp     eax,ecx
        jbe     half_flips_done         ; 2dy <= dx -- no half flip needed

flip_it:

        sub     edx,ecx
        neg     edx
        xor     esi,LF_HALF_FLIP + LF_VERTICAL_FLIP

half_flips_done:

        mov     lsg.lsg_cdx,ecx
        mov     lsg.lsg_cdy,edx

;/*
;** save the flags
;*/
        mov     lsg.lsg_fsLineFlags,esi

;/*
;** call the workhorse to compute the rendering
;*/

        mov     edi,lsg.lsg_cdx
        mov     esi,lsg.lsg_cdy
        mov     eax,lsg.lsg_xA          ; get rid of clipped lines
        cmp     eax,lsg.lsg_xB
        ja      drawlines_next
        call    polyline_workhorse_routine

drawlines_next:

        dec     Count
        jnz     drawlines_loop

;/*
;** restore any hardware defaults
;*/

        call    npfnUnSetup
        call    far_unexclude           ; (I own the semaphore, don't I?)

;/*
;** If the line is not solid and the background mix mode is not
;** transparent, then go back and draw the background line, unless we
;** have already.
;*/

        test    Flags,PF_DOING_BACKGROUND
        jnz     done_background
        cmp     BYTE PTR LineStyle,LINETYPE_SOLID - 1
        jz      done_background
        mov     edi,hddc

        ASSUME  edi:PTR DDC

        cmp     [edi].ddc_la.la_ba.ba_bkmix,ROP_D    ; Leavealone
        je      done_background
        call    polyline_background_init
        or      Flags,PF_DOING_BACKGROUND
        jmp     setup_drawlines
ALIGN 4

done_background:

drawing_all_done:

drawline_good_exit:

        mov     eax,returnvalue

drawline_exit:


        fw_zero <ecx>

                RET

DrawLinesInPath ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = DrawLinesCorrelate
;*
;* DESCRIPTION   =  Performs correlation on the lines in the given path.
;*
;*                  Registers Preserved:
;*                       EDI,ESI,EBP
;*
;*                  Registers Destroyed:
;*                       EBX,ECX,EDX
;*
;* INPUT         =  ESI = DDC
;*                  EDI = curve
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  EAX = 1 if no correlation
;*                  EAX = 2 if correlation
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/

ALIGN 4
DrawLinesCorrelate      PROC    SYSCALL USES esi edi,   cCurves:DWORD
                        LOCAL   npCurve:DWORD, lsg:LINESEGMENT

        ddc?    esi

        ASSUME  esi:PTR DDC, edi:PTR LINE

;/*
;** make sure the correlation rectangle is valid in the DDC
;*/

        test    [esi].ddc_fb,DDC_CORR_INV
        jz      corr_is_valid
        call    recalc_correlate_rect

corr_is_valid:

;/*
;** get the correlation rectangle
;*/

        MOV     ebx,[esi].ddc_prddc
        rddc?   ebx

        ASSUME  ebx: PTR RDDC

        mov     eax,[ebx].rddc_rcsCorr.rcl_xLeft
        mov     ecx,[ebx].rddc_rcsCorr.rcl_xRight
        mov     edx,[ebx].rddc_rcsCorr.rcl_yTop
        mov     ebx,[ebx].rddc_rcsCorr.rcl_yBottom

;/*
;** send null intersections home
;*/

        cmp     eax,ecx
        jge     no_correlation
        cmp     ebx,edx
        jge     no_correlation

;/*
;** stuff the test RECTS into the LINESEGMENT structure
;*/

        mov     lsg.lsg_rcsClip.rcl_xLeft,eax
        mov     lsg.lsg_rcsClip.rcl_yBottom,ebx
        mov     lsg.lsg_rcsClip.rcl_xRight,ecx
        mov     lsg.lsg_rcsClip.rcl_yTop,edx

;/*
;** loop through all the lines
;*/

correlate_loop:

        mov     npCurve,edi

;/*
;** make sure it's a curve
;*/

ifdef FIREWALLS

        cmp     [edi].ln_bIdent,CURVE_IDENTIFIER
        jz      @F

        rip     text,<Curve identifier invalid>

@@:

endif

;/*
;** only do the check if it's really a line
;*/
        cmp     [edi].ln_bType,LINE_IDENTIFIER
        jnz     correlate_next

;/*
;** load up the line info in the registers
;*/

        lea     edx,[edi].ln_ptfxA       ; for POINTFX clipping

        mov     ebx,[edi].ln_ptlA.ptl_x   ; (BX,CX) = point 1
        mov     ecx,[edi].ln_ptlA.ptl_y
        mov     esi,[edi].ln_ptlC.ptl_y   ; (DI,SI) = point 2
        mov     edi,[edi].ln_ptlC.ptl_x

;/*
;** clip the line against the RECTS
;*/

        push    ebp                     ; could just add/sub instead of push/pop
        lea     ebp,lsg                 ; point to LineSegMENT structure
        call    far_clip_line
        pop     ebp

;/*
;** correct for the first pel
;*/

        mov     edx,lsg.lsg_xA          ; DX = xA
        mov     ebx,lsg.lsg_xB          ; BX = xB
        mov     ecx,edi                 ; CX = major extent
        mov     edi,npCurve
        test    [edi].ln_fl,CURVE_DO_FIRST_PEL
        jnz     corrected_for_first_pel
        jecxz   correlate_next          ; watch out for the zero length line!
        test    lsg.lsg_fsLineFlags,LF_LEFT_XCHG
        jnz     we_are_left_exchanged
        cmp     edx,1
        adc     edx,0
        jmp     corrected_for_first_pel
ALIGN 4

we_are_left_exchanged:

        dec     ecx
        cmp     ecx,ebx
        sbb     ebx,0

corrected_for_first_pel:

;/*
;** check for a hit
;*/

        mov     eax,2
        cmp     edx,ebx
        jbe     DrawLinesCorrelate_done

;/*
;** go to the next line
;*/

correlate_next:

        mov     edi,[edi].ln_pcvNext
        dec     cCurves
        jnz     correlate_loop

;/*
;** return the result
;*/

no_correlation:

        mov     eax,1

DrawLinesCorrelate_done:

        RET

DrawLinesCorrelate      ENDP

        end
