;*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 = SLCORR.ASM
;*
;* DESCRIPTIVE NAME = PolyShortLine support routines.
;*
;*
;* VERSION      V2.0
;*
;* DATE         08/19/88
;*
;* DESCRIPTION  These are the routines in SHORTLINE.ASM which are
;*              common between all drivers.
;*
;* FUNCTIONS    ShortlineCorrelate
;*              ComputeShortlineBounds
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   08/19/88                     Robert J. Carragher [t-robc] - Created
;*   05/08/88                     Charles Whitmer [chuckwh]
;*                                   Wrote ShortlineCorrelate
;*
;*****************************************************************************/

        .xlist
        include cmacros.inc
INCL_DDIPATHS           equ     1
INCL_DDIMISC            equ     1
INCL_GRE_LINES          equ     1
INCL_DDICOMFLAGS        equ     1
INCL_GPICORRELATION     equ     1
INCL_GPIPRIMITIVES      equ     1
        include pmgre.inc
        include driver.inc
        include display.inc
        include njmp.mac
        include polyline.inc
        include assert.mac
        .list

        errcode <BITMAP_NOT_SELECTED>

        externA SCREEN_CBSCAN
        externA SCREEN_CY
        externA DOSHUGEINCR

        externFP FSRSemCheck

sBegin  Data
        externB ddcInit
        externB semDriver
sEnd    Data

        externFP far_recalc_correlate_rect ; MAJOR0B.ASM

sBegin  FarCode
        assumes cs,FarCode

        externW FarCodeData

;/***************************************************************************
;*
;* FUNCTION NAME = ShortlineCorrelate
;*
;* DESCRIPTION   =
;*    Performs correlation checking with the given SHORTLINE against the
;*    pick window.We assume that the pick window cannot be empty, and
;*    that the contents of the SHOTLINE sturcture are all unsigned.  We use
;*    the fact that the SHOTRLINE is monotonic in both X and Y.
;*
;*    Registers Destroyed:
;*          BX,CX,DX,ES
;*    Registers Preserved:
;*          SI,DI,BP
;*    Calls:
;*          none
;*
;*
;* INPUT         = DS:SI = DDC
;* OUTPUT        = AX = 1 if no correlation
;*                 AX = 2 if correlation
;*
;* RETURN-NORMAL = None
;* RETURN-ERROR  = None
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   ShortlineCorrelate,<NEAR,PUBLIC,NODATA,NONWIN>,<si,di>
        parmD   psl
        localV  rcs,%(SIZE RECTS)
cBegin

;/*
;**  make sure the pick window is valid in the DDC
;*/

        test    [si].ddc_fb[0],DDC_CORR_INV
        jz      shortline_corr_rect         ;has corr rect in ddc
        call    far_recalc_correlate_rect   ; get the corr rect
shortline_corr_rect:

;/*
;** copy the pick window to the stack
;*/

        les     si,[si].ddc_prddc       ; ES:SI = prddc (SI != DDC!!!)
        rddc?   es,si
        mov     ax,es:[si].rddc_rcsCorr.rcs_xLeft
        mov     bx,es:[si].rddc_rcsCorr.rcs_yBottom
        mov     cx,es:[si].rddc_rcsCorr.rcs_xRight
        mov     dx,es:[si].rddc_rcsCorr.rcs_yTop

;/*
;** make sure it's unsigned, clip it positive!
;*/

        cmp     ax,cx
        jb      @F
        xor     ax,ax                             ; this only happens if AX was negative
@@:     cmp     bx,dx
        jb      @F
        xor     bx,bx                             ; this only happens if BX was negative
@@:

;/*
;** make it inclusive, and save it
;*/

        dec     cx
        dec     dx
        mov     rcs.rcs_xLeft,ax
        mov     rcs.rcs_yBottom,bx
        mov     rcs.rcs_xRight,cx
        mov     rcs.rcs_yTop,dx

;/*
;** loop through all SHORTLINEs
;*/

        les     di,psl
        assumes es,nothing
slc_loop:

;/*
;** find the Y range of the SHORTLINE
;*/

        mov     ax,es:[di].slh_ptsStart.pts_y
        mov     bx,es:[di].slh_ptsStop.pts_y
        inc     ax                                ; allow last Y to be FFFF
        inc     bx
        cmp     ax,bx                             ; move BX towards AX
        jz      slc_next                          ; get rid of empty SHORTLINEs
        sbb     bx,0
        cmp     bx,ax
        adc     bx,-1
        dec     ax                                 ; SHORTLINE Y range is [AX,BX]

;/*
;** load the Y range of the pick window
;*/

        mov     cx,rcs.rcs_yBottom
        mov     dx,rcs.rcs_yTop ; pick window Y range is [CX,DX]

;/*
;** normalize the ranges with respect to the start of the SHORTLINE
;*/

        sub     cx,ax
        sub     dx,ax
        sub     bx,ax
        jae     @F
        neg     cx
        neg     dx
        xchg    cx,dx                             ; pick window range is [CX,DX]
        neg     bx                                ; SHORTLINE range is [0,BX]
@@:

;/*
;** clip the bottom of the pick window to zero, again
;*/

        cmp     cx,dx
        jbe     @F
        xor     cx,cx
@@:

;/*
;** clip the pick window range against the SHORTLINE range
;*/

        cmp     bx,cx                             ; check end of SHORTLINE against
        jb      slc_next                          ;   start of pick window
        cmp     bx,dx                             ; check end of SHORTLINE against
        jb      @F                                ;   end of pick window
        mov     bx,dx
@@:     mov     si,cx                             ; intersection range = [SI,BX]

;/*
;** calculate the X range of the SHORTLINE
;*/

        add     bx,bx
        add     bx,di                             ; [BX].sl_ax => last scan
        add     si,si
        add     si,di                             ; [SI].sl_ax => first scan
        mov     ax,es:[si].sl_ax; AX = first X
        mov     cx,es:[bx].sl_ax[2]
        mov     dx,es:[bx].sl_ax
        inc     cx                                ; allow last X to be FFFF
        inc     dx
        cmp     dx,cx
        sbb     cx,0
        cmp     cx,dx
        adc     cx,-1                             ; CX = last X
        cmp     cx,ax
        ja      @F
        xchg    ax,cx                             ; X range = [AX,CX]
@@:

;/*
;** compare this to the X range of the pick window
;*/

        cmp     ax,rcs.rcs_xRight
        ja      slc_next
        cmp     cx,rcs.rcs_xLeft
        jae     slc_hit

;/*
;** go to the next SHORTLINE
;*/

slc_next:
        mov     cx,es:[di].slh_pslhNext.sel
        mov     di,es:[di].slh_pslhNext.off
        mov     ax,1
        jcxz    slc_done
        mov     es,cx
        assumes es,nothing
        jmp     slc_loop

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

slc_hit:
        mov     ax,2                              ; we have a hit!
slc_done:
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = ComputeShortlineBounds
;*
;* DESCRIPTION   =
;*    Computes a bounding rectangle for a SHORTLINE.  We assume that all
;*    coordinates in the SHORTLINE are unsigned.  This must be the case
;*    since the SHORTLINE is already clipped to the device.
;*
;* INPUT         = psl = pointer to the SHORTLINE
;* OUTPUT        = (AX,BX,CX,DX) = RECTS inclusive bounds
;*
;*                 Registers Destroyed:
;*                       ES
;*
;* RETURN-NORMAL = None
;* RETURN-ERROR  = None
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

cProc   ComputeShortlineBounds,<PUBLIC,NEAR,NODATA,NONWIN>,<si,di>
        parmD   psl
        localV  rcs,%(SIZE RECTS)
cBegin

;/*
;** initialize the RECTS
;*/

        xor     ax,ax
        mov     rcs.rcs_xRight,ax
        mov     rcs.rcs_yTop,ax
        dec     ax
        mov     rcs.rcs_xLeft,ax
        mov     rcs.rcs_yBottom,ax

;/*
;** loop through all the SHORTLINEs
;*/

        les     di,psl
        assumes es,nothing
csb_loop:

;/*
;** put the shortline endpoints into (AX,BX) - (CX,DX)
;*/

        mov     bx,es:[di].slh_ptsStart.pts_y; BX = first Y
        mov     dx,es:[di].slh_ptsStop.pts_y
        mov     si,dx
        inc     si
        inc     bx                                ; allow a last Y of FFFF
        sub     si,bx
        jz      csb_next
        dec     bx
        sbb     cx,cx                             ; CX = FFFF if BX > DX
        xor     si,cx
        sub     si,cx                             ; SI = |DX - BX|
        add     cx,cx
        inc     cx                                ; CX = sgn(DX - BX)
        sub     dx,cx                             ; move DX toward BX by one
        add     si,si                              ; DX = last Y
        add     si,di                             ; [SI].sl_ax => last point
        mov     cx,es:[si].sl_ax; get the last point
        mov     ax,es:[si].sl_ax[-2]; get the second to last point
        inc     cx                                ; allow a last X of FFFF
        inc     ax
        cmp     ax,cx                             ; move the last point towards
        sbb     cx,0                              ;   the second to last point
        cmp     cx,ax
        adc     cx,-1                              ; CX = last X
        mov     ax,es:[di].slh_ptsStart.pts_x; AX = first X

;/*
;** order the unsigned points to get the inclusive rectangle
;*/

        cmp     ax,cx
        jb      @F
        xchg    ax,cx
@@:     cmp     bx,dx
        jb      @F
        xchg    bx,dx
@@:

;/*
;** accumulate the points into the rectangle
;*/
        cmp     ax,rcs.rcs_xLeft
        ja      @F
        mov     rcs.rcs_xLeft,ax
@@:     cmp     bx,rcs.rcs_yBottom
        ja      @F
        mov     rcs.rcs_yBottom,bx
@@:     cmp     cx,rcs.rcs_xRight
        jb      @F
        mov     rcs.rcs_xRight,cx
@@:     cmp     dx,rcs.rcs_yTop
        jb      @F
        mov     rcs.rcs_yTop,dx
@@:

;/*
;** go to the next SHORTLINE
;*/

csb_next:
        mov     cx,es:[di].slh_pslhNext.sel
        jcxz    csb_done
        mov     di,es:[di].slh_pslhNext.off
        mov     es,cx
        assumes es,nothing
        jmp     csb_loop
csb_done:

;/*
;**  return the rectangle
;*/

        mov     ax,rcs.rcs_xLeft

        mov     bx,rcs.rcs_yBottom
        mov     cx,rcs.rcs_xRight
        mov     dx,rcs.rcs_yTop
cEnd

sEnd    FarCode

        end
