;-------------------------------------------------------------------------;
;                                  TIGA                                   ;
;        Copyright (c) 1989-1990  Texas Instruments Incorporated.         ;
;			   All Rights Reserved				  ;
;-------------------------------------------------------------------------;
;   TIGA - Graphics Manager Core                                          ;
;-------------------------------------------------------------------------;
;  TextOut - Output a string of text using the currently selected font,  ;
;  and the current set of text drawing attributes. The destination of    ;
;  the text will either be the screen, or a linear bitmap, as determined ;
;  by a previous call to set_dstbm.                                      ;
;                                                                        ;
;------------------------------------------------------------------------;
;  01/20/89   Original Version Written                     J.G.Littleton ;
;  02/10/89   Fixed preclipping adjustment                 JGL           ;
;  02/27/90   Bounds check on ASCII codes and DFLT char.   JGL           ;
;  03/21/90   Added support for 'fillgaps' effects option and added 3    ;
;             new functions.                               JGL           ;
;  03/27/90   Added direct-mode entry points               WSE           ;
;------------------------------------------------------------------------;
;  Include files
        .include gspreg.inc
        .include gsptypes.inc
        .include gspglobs.inc
        .mlib    gspmac.lib

;  Global Definitions
        .globl  _get_text_xy
        .globl  _text_out
        .globl  _text_outp, _dm_text_outp
        .globl  _set_text_xy, _dm_set_text_xy

;  Register Usage
Rstr    .set    A0          ;pointer to string 
Rfont   .set    A1
Rfirst  .set    A2
Row     .set    A3
Rloc    .set    A4
Rpatn   .set    A5
Rwide   .set    A6
Rdaddr  .set    A7
Rtmp    .set    A9          ;must be odd register
Rextra  .set    A10
Rlast   .set    A11
Rdflt   .set    A12
Rascent .set    A13

_dm_set_text_xy:
        Popc    A8
        move    *A8,A8,1        ;Get y::x
        move    A8,@_envtext+ENVTEXT_XPOSN,1
        rets    2

_set_text_xy:
        Push    A0                                    
        Popc    A0              ;Pop X posn
        Popc    A8              ;Pop Y posn
        sll     16,A8                                   
        movy    A8,A0           ;merge into Y:X
        move    A0,@_envtext+ENVTEXT_XPOSN,1
        Pop     A0
        rets    2

_get_text_xy:
        Push    A0                                    
        setf    16,0,0
        Popc    A0              ;Pop pointer to X posn
        move    @_envtext+ENVTEXT_XPOSN,A8,0
        move    A8,*A0,0        
        Popc    A0              ;Pop pointer to Y posn
        move    @_envtext+ENVTEXT_YPOSN,A8,0
        move    A8,*A0,0        
        Pop     A0
        rets    2

_text_out:
        mmtm    SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13
        mmtm    SP,B0,B1,B2,B7,B10,B11,B12,B13,B14
        Popc    Rdaddr              ;Pop DstX
        Popc    A8                  ;Pop DstY
        sll     16,A8              
        movy    A8,Rdaddr           ;DstY:Dstx
        Popc    Rstr                ;Pop ptr to string
        jruc    common_entry

_text_outp:
        mmtm    SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13
        mmtm    SP,B0,B1,B2,B7,B10,B11,B12,B13,B14
        move    @_envtext+ENVTEXT_XPOSN,Rdaddr,1
        Popc    Rstr                ;Pop ptr to string
        jruc    common_entry

_dm_text_outp:
        mmtm    SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13
        mmtm    SP,B0,B1,B2,B7,B10,B11,B12,B13,B14
        Popc    Rstr                ;Get ptr to string
        move    @_envtext+ENVTEXT_XPOSN,Rdaddr,1

common_entry:
        setf    16,0,0              
;------------------------------------------------------------------------;
; Adjust relative to drawing origin
;------------------------------------------------------------------------;
        move    @_env+ENVIRONMENT_XYORIGIN,A8,1
        addxy   A8,Rdaddr                   
;------------------------------------------------------------------------;
; Check destination bitmap, as text into a linear bitmap is
; not yet supported.
;------------------------------------------------------------------------;
        move    @(_env+ENVIRONMENT_DSTBM),A8,1
        jrnz    ExitTextOut             
;------------------------------------------------------------------------;
;  Get font and text rendering parameters                                ;
;------------------------------------------------------------------------;
        move    @_envtext+ENVTEXT_CHAREXTRA,Rextra,0
        move    @_envtext+ENVTEXT_SELECTED,Rfont,1  
        move    Rfont,B10
        move    *B10(FONT_ROWPITCH),SPTCH,1
        move    *Rfont(FONT_DEFLT),Rdflt,0 
        move    *Rfont(FONT_FIRST),Rfirst,0 
        move    *Rfont(FONT_LAST),Rlast,0 
        move    *Rfont(FONT_ASCENT),Rascent,0 
        move    *Rfont(FONT_DESCENT),Rtmp,0  
        add     Rascent,Rtmp            
        move    Rtmp,DYDX
        sll     16,DYDX             ;DY = Height (DX not yet determined)
;------------------------------------------------------------------------;
;  Determine text alignment. There are two possible cases:               ;
;       1) align=0 - DstY aligned to top of characters                   ;
;       2) align=1 - DstY aligned to baseline of characters              ;
;------------------------------------------------------------------------;
        move    @_envtext+ENVTEXT_ALIGN,Rtmp,0
        jrnz    alignbase
        clr     Rascent             ;top alignment
alignbase:
        sll     16,Rascent          ;[Ascent,0]
        subxy   Rascent,Rdaddr 
;------------------------------------------------------------------------;
;  Perform preclipping. This is only necessary if top of the text        ;
;  straddles the upper clipping rect. In this case we adjust the DY      ;
;  to the number of lines inside the window, and calculate a linear      ;
;  adjustment to be added to each character to start it in the cliprect. ;
;  This linear adjust is equal to the pitch of the font multiplied by    ;
;  the number of lines of the character lying outside the window.        ;
;------------------------------------------------------------------------;
        clr     Rtmp                ;initially assume no linear adj
        cpw     Rdaddr,A8           ;if top of text in window
        jrnv    clipdone            ;   no clip required
        btst    8,A8                ;if DstY below WYEND
        jrnz    ExitTextOut         ;   reject entire string
;  Compute the number of Y lines that the draw origin is above the
;  top of WYSTART. If it is less than equal to zero then no clip required
        clr     B10
        movy    WSTART,B10
        move    Rdaddr,B11
        subxy   B11,B10
        jryle   clipdone
;  If the number of Y lines to top of WYSTART is greater than or equal
;  to the height of the font, then the entire string is above the window
;  and we can reject it.
        cmpxy   DYDX,B10
        jrynn   ExitTextOut
;  We have to chop the top of of characters
        srl     16,B10
        sll     16,B10              ;kill X half of register
        subxy   B10,DYDX            ;DY is now adjusted character height
        move    B10,A8
        addxy   A8,Rdaddr
;  Compute linear adjust value
        move    SPTCH,Rtmp
        srl     16,A8
        mpyu    A8,Rtmp
clipdone:        
        move    *Rfont(FONT_OOWTBL),Row,1
    	add     Rfont,Row
        move	*Rfont(FONT_OLOCTBL),Rloc,1
    	add	Rfont,Rloc
        move	*Rfont(FONT_OPATNTBL),Rpatn,1
        add	Rfont,Rpatn
        add     Rtmp,Rpatn          ;add Y preclipping adjust
        move    *Rfont(FONT_CHARWIDE),Rwide,0
        jrnz    snm_entry
        move    @_envtext+ENVTEXT_EFFECTS,A8,1
        btst    0,A8                ;q: is fill gaps option on?    
        jrz     snp_entry           ;n: use normal routine
        jruc    sep_entry           ;y: use fillgaps routine
;------------------------------------------------------------------------;
;  Entry for: Screen, normal attributes, monospaced                      ;
;------------------------------------------------------------------------;
snm_entry:
        move    Rwide,B10
        movx    B10,DYDX
        setf    8,0,1               ;set up to read character codes
snm_loop:
        move    *Rstr+,A8,1         ;get char code and inc ptr
        jrz     ExitTextOut         ;exit if NULL
;
        cmp     Rlast,A8           
        jrge    snm_dfltchar
        sub     Rfirst,A8
        jrn     snm_dfltchar
        jruc    snm_goodchar
snm_dfltchar:
        move    Rdflt,A8
        jrz     snm_loop
        sub     Rfirst,A8
snm_goodchar:
        sll     4,A8                ;bit index into table
        add     Rloc,A8
        move    *A8,A8,0            ;get loc entry
        add     Rpatn,A8
        move    A8,SADDR
        move    Rdaddr,DADDR
        pixblt  B,XY                ;draw character to screen
        addxy   Rwide,Rdaddr        ;move right by character width
        cpw     Rdaddr,A8               
        btst    6,A8                
        jrz     snm_loop            ;next char is in window
        jruc    ExitTextOut
;------------------------------------------------------------------------;
;  Entry for: Screen, normal attributes, proportional                    ;
;------------------------------------------------------------------------;
snp_entry:
        setf    8,0,1               ;set up to read character codes
snp_loop:
        move    *Rstr+,A8,1         ;get char code and inc ptr
        jrz     ExitTextOut         ;exit if NULL
;
        cmp     Rlast,A8           
        jrge    snp_dfltchar
        sub     Rfirst,A8
        jrn     snp_dfltchar
        jruc    snp_goodchar
snp_dfltchar:
        move    Rdflt,A8
        jrz     snp_loop
        sub     Rfirst,A8
snp_goodchar:
        sll     4,A8                ;bit index into table
        move    A8,Rtmp             ;save bit index
        add     Row,A8              ;add base of offset/width table
        move    *A8,Rwide,0         ;get offset/width entry
        cmpi    0ffffh,Rwide
        jrz     snp_dfltchar        ;   skip to next char
;
        add     Rloc,Rtmp           ;index into location table
        move    *Rtmp+,A8,0         ;char image bit offset
        move    *Rtmp,Rtmp,0        ;NEXT char image bit offset
        sub     A8,Rtmp             ;delta = image width
        add     Rpatn,A8            ;points to character image
        move    A8,SADDR               
;
        move    Rwide,A8            ;ow entry
        zext    Rwide,1             ;isolate character width
        srl     8,A8                ;isolate character offset
        sext    A8,1                ;sign extend it 
;                
        addxy   Rdaddr,A8
        move    A8,DADDR            ;start coords for drawing
        move    Rtmp,B10            
        movx    B10,DYDX            ;[Height, ImageWidth]
        pixblt  B,XY                ;draw character to screen

        addxy   Rwide,Rdaddr        ;move right by character width
        addxy   Rextra,Rdaddr
        cpw     Rdaddr,A8               
        btst    6,A8                
        jrz     snp_loop            ;next char is in window
        jruc    ExitTextOut
;------------------------------------------------------------------------;
;  Entry for: Screen, fillin gaps, proportional                          ;
;------------------------------------------------------------------------;
sep_entry:
        setf    8,0,1               ;set up to read character codes
        sext    Rextra,0
sep_loop:
        move    *Rstr+,A8,1         ;get char code and inc ptr
        jrz     ExitTextOut         ;exit if NULL
;
        cmp     Rlast,A8           
        jrge    sep_dfltchar
        sub     Rfirst,A8
        jrn     sep_dfltchar
        jruc    sep_goodchar
sep_dfltchar:
        move    Rdflt,A8
        jrz     sep_loop
        sub     Rfirst,A8
sep_goodchar:
        sll     4,A8                ;bit index into table
        move    A8,Rtmp             ;save bit index
        add     Row,A8              ;add base of offset/width table
        move    *A8,Rwide,0         ;get offset/width entry
        cmpi    0FFFFh,Rwide        ;if not defined
        jrz     sep_dfltchar        ;   use default char
;
        add     Rloc,Rtmp           ;index into location table
        move    *Rtmp+,A8,0         ;char image bit offset
        move    *Rtmp,Rtmp,0        ;NEXT char image bit offset
        sub     A8,Rtmp             ;delta = image width
        add     Rpatn,A8            ;points to character image
        move    A8,SADDR               
;
        move    Rwide,A8            ;ow entry
        zext    Rwide,1             ;isolate character width
        srl     8,A8                ;isolate character offset
        sext    A8,1                ;sign extend it 
;  GAP1 = (offset > 0) ? offset : 0
        jrle    sep_nofillgap1
        move    A8,B10                  
        movx    B10,DYDX            ;offset is now DX
        move    Rdaddr,DADDR
        Swap    COLOR1,COLOR0
        fill    XY
        Swap    COLOR1,COLOR0
sep_nofillgap1:
        move    Rtmp,B10            
        movx    B10,DYDX            ;[Height, ImageWidth]
        move    A8,Rtmp             ;save offset for later
        addxy   Rdaddr,A8
        move    A8,DADDR            ;start coords for drawing
        pixblt  B,XY                ;draw character to screen
;  GAP2 = (width+extra)-(offset+imagewidth)
;  Fill in gap before character. Gap Width=offset
;  offset
        move    Rtmp,B10
        move    DYDX,B11
        sext    B11,0
        add     B11,B10             ;offset+imagewidth
        move    Rwide,Rtmp
        add     Rextra,Rtmp
        move    Rtmp,B11            ;width+extra
        sub     B10,B11
        jrle    sep_nofillgap2
        move    Rdaddr,DADDR
        zext    B10,0
        addxy   B10,DADDR
        movx    B11,DYDX
        Swap    COLOR1,COLOR0
        fill    XY
        Swap    COLOR1,COLOR0
sep_nofillgap2:
        addxy   Rtmp,Rdaddr         ;move right by (char width + extra)
        cpw     Rdaddr,A8               
        btst    6,A8                
        jrz     sep_loop            ;next char is in window
ExitTextOut:
        setf    32,0,1              ;restore FS1
        move    Rdaddr,A8               
        addxy   Rascent,A8
        move    A8,@_envtext+ENVTEXT_XPOSN,1
        zext    A8,0
        mmfm    SP,B0,B1,B2,B7,B10,B11,B12,B13,B14
        mmfm    SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13
        rets    2                   

