;-------------------------------------------------------------------------;
;                                  TIGA                                   ;
;        Copyright (c) 1987-1990  Texas Instruments Incorporated.         ;
;			   All Rights Reserved				  ;
;-------------------------------------------------------------------------;
;   TIGA - Graphics Manager Extension                                     ;
;-------------------------------------------------------------------------;
;                                                                         ;
; fill_oval and patnfill_oval functions                                   ;
;                                                                         ;
;   The fill_oval function                                                ;
;   draws a solid-filled ellipse given the minimum enclosing rectangle    ;
;   for the ellipse.  The enclosing rectangle is defined in terms of      ;
;   its width w, height h, and the x-y coordinates at its top left        ;
;   corner, (xleft, ytop).  The interior of the ellipse is filled with    ;
;   solid color 1.                                                        ;
;                                                                         ;
;   The patnfill_oval function draws a pattern-filled ellipse given a     ;
;   minimum enclosing rectangle specified in the same way as for the      ;
;   fill_oval function.  The interior is filled with the current 16x16    ;
;   pattern in colors 0 and 1.                                            ;
;-------------------------------------------------------------------------;
; Usage:  fill_oval(w, h, xleft, ytop);                                   ;
;         patnfill_oval(w, h, xleft, ytop);                               ;
;                                                                         ;
; Description of stack arguments:                                         ;
;   int w, h;  /* width and height of enclosing rectangle */              ;
;   int xleft, ytop;  /* coordinates at top left of encl. rect. */        ;
;                                                                         ;
; Returned in register A8:  Void (undefined).                             ;
;                                                                         ;
; Registers altered:  A8                                                  ;
;-------------------------------------------------------------------------;
; Revision history:                                                       ;
;   3/12/87...Original version written...................Jerry Van Aken   ;
;   9/15/88...Added TIGA dm, globals and dstbm check.....Graham Short     ;
;-------------------------------------------------------------------------;
;
        .title    'filled ellipse'
        .file     'filloval.asm'
;
;  INCLUDE GLOBAL DEFINITIONS
;
       .include   gsptypes.inc
       .include   gspglobs.inc          
;
;     DECLARE GLOBAL FUNCTION NAME
;
        .globl    _fill_oval,     _dm_fill_oval
        .globl    _patnfill_oval, _dm_patnfill_oval
;
;     ENTRY POINTS
;
_dm_fill_oval:
        MMTM      SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A13
        MMTM      SP,B0,B2,B7,B10,B11,B12,B13,B14
        CLR       B0                  ;B0 = 0 ==> solid fill
        JRUC      DM_EP
;
_dm_patnfill_oval:
        MMTM      SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A13
        MMTM      SP,B0,B2,B7,B10,B11,B12,B13,B14
        move      @_pattern+PATTERN_HSRV,B0,1   ;subroutine for pattern fill
;
DM_EP:
* Get four arguments command buffer data area
        MOVE      *-A14,A8,1          ;get pointer to data area
        SETF      16,0,0
        MOVE      *A8+,A0,0           ;get 1st argument, w
        MOVE      *A8+,A1,0           ;get 2nd argument, h
        MOVE      *A8+,A2,0           ;get 3rd argument, xleft
        MOVE      *A8+,A3,0           ;get 4th argument, ytop
        jruc      common_ep
;
_fill_oval:
        MMTM      SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A13
        MMTM      SP,B0,B2,B7,B10,B11,B12,B13,B14
        CLR       B0                  ;B0 = 0 ==> solid fill
        JRUC      CP_EP

_patnfill_oval:
        MMTM      SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A13
        MMTM      SP,B0,B2,B7,B10,B11,B12,B13,B14
        move      @_pattern+PATTERN_HSRV,B0,1   ;subroutine for pattern fill
;
CP_EP:
* Pop four arguments from stack.
        MOVE      *-A14,A0,1          ;pop 1st argument, w
        MOVE      *-A14,A1,1          ;pop 2nd argument, h
        MOVE      *-A14,A2,1          ;pop 3rd argument, xleft
        MOVE      *-A14,A3,1          ;pop 4th argument, ytop
;
;     TWO ENTRY POINTS JOIN HERE
;
common_ep:
;
; check for destination bitmap pointing to the screen, if not abort for now
; linear drawing capability will be added at a later time
;
        MOVE      @(_env+ENVIRONMENT_DSTBM),A8,1    ; destination bit-map global
        JRNZ      DONE                      ; if zero, dstbm is set to screen
;
;     MAIN ALGORITHM
;
* Calculate starting x1, y1 and y2 values.
        ADD       A2,A2                     ;
        ADD       A0,A2                     ;
        SRL       1,A2                      ;initial x1 = xleft + w/2
        SLL       16,A3                     ;concatenate y1, x1
        MOVY      A3,A2                     ;where y1 = ytop
        MOVE      A1,A3                     ;
        SUBK      1,A3                      ;
        SLL       16,A3                     ;concatenate y1, x1
        ADDXY     A2,A3                     ;where y1 = ytop + h - 1
        MOVE      @_env+ENVIRONMENT_XYORIGIN,A8,1   ;viewport origin displacement
        ADDXY     A8,A2                     ;screen relative coordinates
        ADDXY     A8,A3                     ;
* Calculate k1 = 8*w*w and k2 = 8*h*h.
        SETF      16,0,1              ;field size = 16 for multiply
        MOVE      A1,A5               ;copy h
        MPYU      A5,A5               ;
        MOVE      A5,A4               ;
        SLL       3,A4                ;k1 = 8*h*h
        MOVE      A0,A5               ;copy w
        MPYU      A5,A5               ;
        SLL       3,A5                ;k2 = 8*w*w
        SETF      32,0,1              ;restore field size to 32
* Calculate 32*h*w*w to 64 bits as a precaution against overflow.
        MOVE      A1,A6               ;copy h
        SLL       2,A6                ;calculate 4*h
        MPYU      A5,A6               ;compute 32*h*w*w to 64 bits
* Is ellipse's width or height more likely to cause arithmetic overflow?
        CMP       A1,A0               ;is w >= h?
        JRLT      FO1                 ;jump if w < h
* w >= h:  Will quantity 32*h*w*w overflow 32-bit register?
        LMO       A6,A8               ;measure amount of overflow
        JRZ       FO3                 ;jump if no overflow
        JRUC      FO2                 ;jump to prescale code
* w < h:  Will quantity 32*w*h*h overflow 32-bit register?
FO1:
        MOVE      A0,A8               ;copy w
        SLL       2,A8                ;calculate 4*w
        MPYU      A4,A8               ;compute 32*w*h*h to 64 bits
        LMO       A8,A8               ;measure amount of overflow
        JRZ       FO3                 ;jump if no overflow
* Prescale all loop constants and variables by the same amount.
FO2:
        SLL       A8,A6               ;prescale 32*h*w*w
        SRL       A8,A7               ;
        OR        A6,A7               ;
        SRL       A8,A4               ;prescale k1 = 8*h*h
        SRL       A8,A5               ;prescale k2 = 8*w*w
* Calculate initial values of loop variables v1, v2 and d.  Initially
* v2 = -4*h*w*w.  If w is even, v1 = 0 and d = h*h+w*w-2*h*w*w.
* If w is odd, v1 = 4*h*h and d = 4*h*h+w*w-2*h*w*w.
FO3:
        CLR       A11                 ;v1 = 0
        SRL       1,A7                ;
        NEG       A7                  ;-16*h*w*w
        MOVE      A7,A13              ;
        SRA       2,A13               ;v2 = -4*h*w*w
        ADD       A4,A7               ;
        ADD       A5,A7               ;8*d = 8*h*h+8*w*w-16*h*w*w
        MOVK      1,A9                ;x increment = +1
        MOVI      010000h,A10         ;y increment = +1
        MOVE      A10,B7              ;initial wfill = 0
        BTST      0,A0                ;is w odd?
        JRZ       F04                 ;jump if w even
; w is odd--
        MOVE      A4,A11              ;
        SRL       1,A11               ;v1 = 4*h*h
        SUB       A4,A7               ;8*w*w-16*h*w*w
        ADDK      1,B7                ;initial wfill = 1
F04:
        SRA       3,A7                ;
        ADD       A11,A7              ;initial d
        MOVE      B0,B0               ;solid fill or pattern fill?
        JRNZ      PATNFILL            ;jump if pattern fill
*
* Main Loop #1:  Draw solid-filled ellipse.
*
        MOVE      A7,A7               ;check sign of d
LOOP1:
        JRNN      F05                 ;jump if d >= 0
* Step in horizontal direction
        SUBXY     A9,A2               ;--x1
        SUBXY     A9,A3               ;
        ADDK      2,B7                ;wfill += 2
        ADD       A4,A11              ;v1 += k1
        ADD       A11,A7              ;d += v1
        JRUC      LOOP1               ;
F05:
* Decrement count; if negative, break out of loop.
        SUBK      2,A1                ;h -= 2
        JRN       BREAK1              ;if h < 0, break out of loop
* Fill two horizontal lines in top and bottom halves of ellipse.
        MOVE      A2,B2               ;DADDR = y1::x1
        FILL      XY                  ;fill line in top of oval
        MOVE      A3,B2               ;DADDR = y2::x1
        FILL      XY                  ;fill line in bottom half
* Move vertically to next fill line.
        ADDXY     A10,A2              ;++y1
        SUBXY     A10,A3              ;--y2
        ADD       A5,A13              ;v2 += k2
        ADD       A13,A7              ;d += v2
        JRUC      LOOP1               ;loop again
* End of Loop:  If height of oval is odd, fill line thru center.
BREAK1:
        BTST      0,A1                ;is height odd ?
        JRZ       DONE                ;jump if height is even
        MOVE      A2,B2               ;DADDR = y1::x1
        FILL      XY                  ;fill strip thru center
        JRUC      DONE                ;done
*
* Main Loop #2:  Draw pattern-filled ellipse.
*
PATNFILL:
        MOVE      A7,A7               ;check sign of d
LOOP2:
        JRNN      F06                 ;jump if d >= 0
* Step in horizontal direction
        SUBXY     A9,A2               ;--x1
        SUBXY     A9,A3               ;
        ADDK      2,B7                ;wfill += 2
        ADD       A4,A11              ;v1 += k1
        ADD       A11,A7              ;d += v1
        JRUC      LOOP2               ;
F06:
* Decrement count; if negative, break out of loop.
        SUBK      2,A1                ;h -= 2
        JRN       BREAK2              ;if h < 0, break out of loop
* Fill two horizontal lines in top and bottom halves of ellipse.
        MOVE      A2,B2               ;DADDR = y1::x1
        CALL      B0                  ;fill line in top of oval
        MOVE      A3,B2               ;DADDR = y2::x1
        CALL      B0                  ;fill line in bottom half
* Move vertically to next fill line.
        ADDXY     A10,A2              ;++y1
        SUBXY     A10,A3              ;--y2
        ADD       A5,A13              ;v2 += k2
        ADD       A13,A7              ;d += v2
        JRUC      LOOP2               ;loop again
* End of Loop:  If height of oval is odd, fill line thru center.
BREAK2:
        BTST      0,A1                ;is height odd ?
        JRZ       DONE                ;jump if height is even
        MOVE      A2,B2               ;DADDR = y1::x1
        CALL      B0                  ;fill strip thru center

* Restore registers and return.
DONE:
        MMFM      SP,B0,B2,B7,B10,B11,B12,B13,B14
        MMFM      SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A13
        RETS      2                   ;Return
        .end

