'===========================================================================
' Subject: VGA FONTS (USING VGA-BIOS)         Date: 06-07-97 (11:13)       
'  Author: Andras Hoeffken                    Code: QB, PDS                
'  Origin: FidoNet QUIK_BAS Echo            Packet: EGAVGA.ABC
'===========================================================================
'the following tool introduces new features of printing text in 
'SCREEN 12 mode. Especially useful to label e.g. graphical curves.

'VGA_FONT - VGA-(Hardware)Fonts Vs.1.0 for QuickBasic 4.5 and Basic PDS 7.0
'           With SCREEN 12 three fonts are taken from the VGA-BIOS and used to
'           construct 5 different sizes of screen text.

'June 1996  Andras Hoeffken,  2:2480/13.34 @fidonet / ah@confusion.rmc.de

'Adapted to QB4.5 from the original version:
     '*** GPrintX - E.F.Deel, 1/15/93
     '*** Print graphics mode characters in selected
     '*** sizes at any location; with or without background.
     '*** Public domain, use it, abuse it, but don't blame me.
     '*** For Microsoft Professional Basic PDS 7.0 (originally NOT for QB4.5)

     DEFINT A-Z

     TYPE regtype
       ax    AS INTEGER
       bx    AS INTEGER
       cx    AS INTEGER
       dx    AS INTEGER
       bp    AS INTEGER
       si    AS INTEGER
       di    AS INTEGER
       flags AS INTEGER
       ds    AS INTEGER
       es    AS INTEGER
     END TYPE
     DIM SHARED inreg AS regtype, outreg AS regtype
     DECLARE SUB interruptx (inum, inreg AS regtype, outreg AS regtype)
    
     DECLARE SUB GPrintX (Text$, X, Y, Colr, TSize)

     SCREEN 12        'Standard VGA Graphics 480x640x16

     LOCATE 1, 27
     PRINT "Textfonts for SCREEN 12"
     LOCATE 2, 26
     PRINT "(INT 10h, AH=11h, AL=30h)"

     LINE (0, 0)-(199, 199), 2, BF      ' a green box
     LINE (200, 200)-(399, 399), 1, BF  ' a blue
     LINE (400, 0)-(599, 199), 5, BF    ' a magenta

'*** Show 8x16 Characters
     Text$ = "Example of text (8x16)" 'Some text
     Colr = 4                      'red text over existing background (BG=0)
     TSize = 16                    '8X16 characters
     X = 0: Y = 0                  'Start at extreme upper left
     FOR i = 1 TO 40               'print string 40 times
       GPrintX Text$, (X), Y, Colr, TSize    'print it
       X = X + 12                  'increment one & a half columns
       Y = Y + 12                  '... and 3/4 of a line
     NEXT i                        'and do it again

'*** Show 8x14 Characters
     Text$ = "Example of text (8x14)" 'Some text
     Colr = 64                     'black text over red background (4*16 + 0)
     TSize = 14                    '8X14 characters
     X = 487: Y = 0                'Start at upper right
     FOR i = 1 TO 34               'print string 34 times
       GPrintX Text$, (X), Y, Colr, TSize    'print it
       X = X - 16                  'decrement 2 columns
       Y = Y + 14                  'increment a line
     NEXT i                        'and do it again

'*** Show 8x8 Characters
     Text$ = "Example of text (8x8)" 'Some text
     Colr = 2                      'green text over existing background (BG=0)
     TSize = 8                     '8X8 characters
     X = 248: Y = 32               'Start near top center
     FOR i = 1 TO 55               'print string 55 times
       GPrintX Text$, (X), Y, Colr, TSize    'print it
       Y = Y + 8                   'increment a line
     NEXT i                        'and do it again

'*** Show 16x16 Characters
     Colr = 71                     'Gray letters over red background (4*16+7)
     TSize = 32                    'Double Wide
     Text$ = "Example of double wide text (16x16)"
     GPrintX Text$, 0, 240, Colr, TSize

'*** Show 16x32 Characters
     Colr = 7 * 16                 '5 = Magenta Text over current background
     TSize = 64                    'Double Wide, Double High
     Text$ = "Double wide, Double high text (16x32)"
     GPrintX Text$, 0, 270, Colr, TSize

'*** Finish
     GPrintX "Press a key to continue", 456, 310, 7 * 16 + 4, 16
     DO: LOOP UNTIL LEN(INKEY$)    'wait for a keystroke

     SCREEN 0
END '=======================================================================

SUB GPrintX (Text$, X, Y, Colr, TSize) STATIC
   '(STATIC ==> all local variables are defined static!)

   '*** GRAPHIC TEXT PRINTING SUBROUTINE ***
   'X, Y = Graphics mode pixel coordinates
   'Colr = combined FG and BG (BG*16 + FG), BG = 0 leaves existing background
   'TSize is coded text size
   '   8  = 8x8 font
   '   14 = 8x14 font
   '   16 = 8x16 font
   '   32 = Double wide 8x16 font  (--> 16x16)
   '   64 = Double wide, double high, 8x16 font (--> 16x32)

     l = LEN(Text$)
     IF l = 0 THEN EXIT SUB    'abort if no text is given

     IF GPXFlg = 0 THEN        'test avoids re-initializing 2wide masks
       REDIM C2X(15)           'bit masks for producing double wide characters
       C2X(0) = 0              'pre-calculated masks provide max. speed
       C2X(1) = 3: C2X(2) = 12: C2X(3) = 15: C2X(4) = 48: C2X(5) = 51
       C2X(6) = 60: C2X(7) = 63: C2X(8) = 192: C2X(9) = 195: C2X(10) = 204
       C2X(11) = 207: C2X(12) = 240: C2X(13) = 243: C2X(14) = 252
       C2X(15) = 255
       GPXFlg = -1        'Set the flag so we don't do this again next time
     END IF

     IF TSize <> SaveSze THEN 'another test so we don't repeat if not required
       dx = 8: Expand = 0
       SELECT CASE TSize
         CASE 8: Ftype = &H300: Font = 8: DY = 8
         CASE 14: Ftype = &H200: Font = 14: DY = 14
         CASE 16: Ftype = &H600: Font = 16: DY = 16
         CASE 32: Ftype = &H600: Font = 16: DY = 16: dx = 16: Expand = 1
         CASE 64: Ftype = &H600: Font = 16: DY = 32: dx = 16: Expand = 2
       END SELECT
       inreg.ax = &H1130                'AH = 11h: access of an internal font
                                        'AL = 30h: get address of a font
       inreg.bx = Ftype                 'BX = type of font
       CALL interruptx(&H10, inreg, outreg) 'INT 10h, gives:
       FontSeg = outreg.es                  ' segment
       FontAdrs = outreg.bp                 ' offset
       SaveSze = TSize                  'save the size for next time
     END IF

     FG = Colr AND 15                   'split out FG and BG colors
     BG = Colr \ 16

     DEF SEG = FontSeg                  'segment of VGA-BIOS

     FOR i = 1 TO l                     'For each character in string
       cc = ASC(MID$(Text$, i, 1))      'get character code (0...255)
       Addr = Font * cc + FontAdrs      'find the address (in VGA-BIOS)
       CY = Y                           'top of character location
       IF BG THEN LINE (X, Y)-(X + dx - 1, Y + DY - 1), BG, BF'draw background
       FOR j = 0 TO Font - 1            'For each scanline in font
         scanline = PEEK(Addr + j)      'get the scanline byte
         IF Expand THEN                 'Double wide or Double High characters
           lo = scanline AND 15         'low nibble of scanline
           hi = scanline \ 16           'high nibble
           FOR k = 1 TO Expand
             zwi& = CLNG(C2X(hi)) * 256 'long integer: lo byte --> hi byte
             IF zwi& > 32767 THEN scanline = zwi& - 65536 ELSE scanline = zwi&
             LINE (X, CY)-(X + 7, CY), FG, , scanline  'tranfer scanline
             zwi& = CLNG(C2X(lo)) * 256 'long integer: lo byte --> hi byte
             IF zwi& > 32767 THEN scanline = zwi& - 65536 ELSE scanline = zwi&
             LINE (X + 8, CY)-(X + 15, CY), FG, , scanline  'tranfer scanline
             CY = CY + 1                'next scan line
           NEXT k                       'again if double high
         ELSE                           'normal characters
           zwi& = CLNG(scanline) * 256  'long integer: lo byte --> hi byte
           IF zwi& > 32767 THEN scanline = zwi& - 65536 ELSE scanline = zwi&
           LINE (X, CY)-(X + 7, CY), FG, , scanline  'tranfer scanline
           CY = CY + 1                  'next scan line
         END IF
       NEXT j
       X = X + dx                       'next character
     NEXT i
    
     DEF SEG                            'back to DGROUP

END SUB
