[comp.sources.amiga] v02i059: fasttext - speed up your text V3.0

page@swan.ulowell.edu (Bob Page) (11/10/88)

Submitted-by: page@swan.ulowell.edu (Bob Page)
Posting-number: Volume 2, Issue 59
Archive-name: fonts/fasttext30.1

These routines utilize the blitter to speed up rendering of fonts of
any height, and of 4-16 pixels in width.  Other fast text rendering
routines only speed up rendering of 8 bit wide fonts.  This code can
be linked in with your programs.  A skinny font is included so you
can have more columns in a window.

[I lost the original submitter's address, sorry.  ..Bob]

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	Announcement
#	8.uu
#	wide.font.uu
#	FastText.asm
#	FastText.doc
#	Ftest.c
# This archive created: Wed Nov  9 21:22:54 1988
cat << \SHAR_EOF > README
FastText Copyright 1988 by Darren M. Greenwald

This is the first revision of my new FastText() code which
can be linked in, and included within your programs.  These
new routines utilize the blitter, and speed up rendering of
fonts of any height, and of 4-16 pixels in width.  As far
as I know, this is a first.  My own, and other fast text
rendering routines only speed up rendering of 8 bit wide
fonts.

This new Fast Text code is also somewhat easier to use then
the previous two versions I released in 1978.

Oh, I went ahead, and added a font I created some time ago
called WIDE.FONT.  Despite the name, WIDE.FONT is a
skinnier 6 bit wide, 8 bit high Topaz style font.  It is a
non-proportional font suitable for use with SetFont - using
it effectively gives you more columns to work with, hence
the name WIDE.FONT!

This new FastText() code is Copyrighted!  You must ask
permission to utilize this code in any commercial, or
shareware ventures.  Read the FastText.doc file for more
information on how to contact me.

SHAR_EOF
cat << \SHAR_EOF > Announcement
This is my latest blitter based fast text rendering routines which are
unique in that they speed up rendering of non-proportional fonts of any
height, and from 4-16 pixels in width.	This stuff is written in assembly,
and a test program written in Manx C is included to show off the speed
difference between FastText(), and Text().  Source code is included - this
file may be distributed freely, but permission is required to use these
routines in commercial, and shareware products.

FastText Copyright 1988 by Darren M. Greenwald - Enjoy!

SHAR_EOF
cat << \SHAR_EOF > 8.uu

begin 644 8
M```#\P`````````!``````````````$-```#Z0```0UP`$YU```````````,^
M`````!H/@``!````````````````````````````````````````````````J
M```````````,`````!H``````\0`"`!#``8`!@`!```@?P```&X`2````JX`*
M``````````")%"`$!!$``````'"''!/C/G'```@$''"/'./OG(OCLN(HG/'/%
M'/HHHHHOG`#B`!`(`#`#`,"`H&```````$```````A&&@`')%'HJ!""-B```V
M`(F(HC($(HHA!!`"(HG$HI$DHHB`DD(LHDHDHJHHHMHHD(`G`!`(`!`$@$``'
M("```````$``````!!!+``'`/L)J"$!'"````IB!`E/(`HHA!"/A`KE$H(D$Z
M((B`E$-NHDHDH"(HHG-A$$`M@`G+'%'$&E&`HB(O'+&M'O)(HHHOA!!```"`^
M%'#&@$!/O@/@!/B"#)`O!''@`$``A*HG((G')OB`F$/KHG(G'"(HJB'"$"`H'
M@`!-HK(N)&B`I"-HHDI&H$)(JE(I&!`@``"`/AF+`$!'"```",B$`O@HB(@@J
M`"`!"+ODH(D$(HB(E$JIHD*E`B(E/G"$$!`@``'(H)/D)$B`N"*HHDI$G$)(6
MJB(B!!!`````%/,I`""-B!`!$(B(HA(HB(A!!!/B`((DHI$D(HB(DDHHHD)DY
MHB(G-MB(D`@@``)(HI($&$B`I"(HHG'$`DI'-E'$A!!```"`%"(F@!$``!`!0
M('/OG#O'"'.!!`@$"'(O'./N'HOG,OHHG.'LG''B(HG/G`#@``&G'&G.!DG(&
MHG(HG$!./#&B-HB/@A&``````````````"``````````````"```````````]
M```````````@````````````/P``````/``'`````.!@``````,`````````E
M``8`!@`&``P`!@`2``8`&``&`!X`!@`D``8`*@`&`#``!@`V``8`/``&`$(`.
M!@!(``8`3@`&`%0`!@!:``8`8``&`&8`!@!L``8`<@`&`'@`!@!^``8`A``&J
M`(H`!@"0``8`E@`&`)P`!@"B``8`J``&`*X`!@"T``8`N@`&`,``!@#&``8`Z
MS``&`-(`!@#8``8`W@`&`.0`!@#J``8`\``&`/8`!@#\``8!`@`&`0@`!@$.A
M``8!%``&`1H`!@$@``8!)@`&`2P`!@$R``8!.``&`3X`!@%$``8!2@`&`5``S
M!@%6``8!7``&`6(`!@%H``8!;@`&`70`!@%Z``8!@``&`88`!@&,``8!D@`&/
M`9@`!@&>``8!I``&`:H`!@&P``8!M@`&`;P`!@'"``8!R``&`<X`!@'4``8!@
MV@`&`>``!@'F``8![``&`?(`!@'X``8!_@`&`@0`!@(*``8"$``&`A8`!@(<6
M``8"(@`&`B@`!@(N``8"-``&`CH`!@)```8"0````^P````$``````````X`?
3``!$````7````&(````````#\CH`Q
``
end
size 1144
SHAR_EOF
cat << \SHAR_EOF > wide.font.uu

begin 644 wide.font
M#P```5=)1$4O.```````````````````````````````````````````````@
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
G````````````````````````````````````````````````"`!#+
``
end
size 264
SHAR_EOF
cat << \SHAR_EOF > FastText.asm
*
* Fast font Assembly sub-routines
* 
* Copyright 1988 by Darren M. Greenwald
*
* Rev. 3.0 9/27/88
*
* New blitter based routine to handle any size font
*
* This new routine relies on the brute force approach, and the blitter!
* The font data is unpacked, and the masking, shifting, and target
* addresses are pre-calculate for speed.
*
* This version of the fast text routines can render fonts of any height,
* and of any size from 4-16 pixels wide.  Wider fonts, proportional fonts,
* and styles are currently not supported.
*
* This routine is copyrighted, and freely distributable.  It may not be
* used in any commercial product, shareware product, or commercial
* publication  without permission.  It is permissible to release this file
* as part of a public domain collection, or on a telecommunication service
* as long as no "special charge" is made for this program;
* "special charge" does not include standard charges for replication
* of the media, or use of the system.
*
* The intent of the above should be clear - I did the work, and am giving
* the code away for free.  While you may use it, you may not
* profit from it.
*
* The previous fast text routines I released in 1987 were public domain
* in every sense of the word.  In order to use these routines in a
* commercial, or shareware venture, you must ask permission - at the most
* I may ask in return that you include credit for the use of these
* routines within your program's documentation, and/or free registration, or
* a copy of the software you are developing.  In addition, I will provide
* answers if you have any questions, and just maybe provide assistance
* with modifying the routines to suit your needs.  All I ask is that you
* ask!
*

            XDEF     _InitFastText   ;Declare these labels visible to linker
            XDEF     _FreeFastText
            XDEF     _FastText

            XREF     _GfxBase
            XREF     _LVOAllocMem
            XREF     _LVOFreeMem
            XREF     _LVOBltTemplate
            XREF     _LVOText
            XREF     _OwnBlitter
            XREF     _DisownBlitter
            XREF     _WaitBlit

            include  "SYS2:asm/exec/types.i"
            include  "SYS2:asm/graphics/text.i"
            include  "SYS2:asm/hardware/blit.i"
            include  "SYS2:asm/hardware/custom.i"
            include  "SYS2:asm/graphics/rastport.i"
            CSEG

* ---------------------------------------------------------------------
* Call this routine to free any memory allocated by InitFastText() 
* below.
* 
* This is a safe routine - it can be called safely even if InitFastText()
* fails.
* ---------------------------------------------------------------------
_FreeFastText:

            MOVE.L   FontData,D0       ;safety check for NULL ptr
            BEQ      nodata
            MOVEA.L  D0,A1             ;address of buffer to free
            MOVE.L   FontSize,D0       ;size of buffer to free
            MOVEA.L  $4,A6             ;ExecBase
            JSR      _LVOFreeMem(A6)
            CLR.L    FontData          ;set to NULL

nodata:

            MOVE.L   Imagebuf,D0
            BEQ      nobuf             ;safety valve
            MOVEA.L  D0,A1             ;address of buffer
            MOVE.L   Imagesize,D0      ;size of working buffer
            MOVEA.L  $4,A6
            JSR      _LVOFreeMem(A6)
            CLR.L    Imagebuf          ;set to NULL

nobuf:      RTS

* ---------------------------------------------------------------------
* This routine does a few things for you.
*
* It checks to make sure the font size is within 4 bits wide, and 16
* bits wide.  It also checks for PROP fonts.  Wider/thinner fonts, and
* PROP fonts will cause this routine to fall through, and set up to
* use Text() instead of the fast text routines.  This is transparent, so
* you do not have to write additional code to handle anything if
* the FastText() routine cannot be used.
*
* It allocates 2 chip ram buffers - one for the unpacked font data,
* and the other for an image buffer to draw in.  The amount of space
* required is calculated for you based on the font size per the pointer
* to a TextFont structure which is passed via the stack.
*
* The font data is unpacked into words using an edge-to-edge model.
* Extraneous bits are masked out, and the image data is left justified.
*
* The blitter masks, shifts, and destination addresses are pre-calcuated
* for speed during rendering.
*
* An indirect function pointer is set-up based on the font width.  8 bit
* wide fonts can be rendered faster then other fonts, so a special
* blitter routine is devoted to handling 8 bit wide fonts.  Often this is
* the most common font, so it makes sense to use this capability.
*
* ---------------------------------------------------------------------

font        EQU      04       ;stack offset
 
_InitFastText:

            MOVEA.L  font(SP),A2       ;address of a text font struct

            TST.L    tf_CharSpace(A2)  ;is this a prop font?
            BNE      Initfailed

            CLR.L    D0

            MOVE.W   tf_XSize(A2),D0
            MOVE.L   D0,XSize          ;save
            CMP.W    #16,D0            ;check bounds of this
            BHI      Initfailed

            MOVE.W   tf_YSize(A2),D0
            MOVE.L   D0,YSize          ;save
            CMP.W    #4,D0             ;check bounds of this
            BLT      Initfailed

            MOVE.W   tf_Baseline(A2),Baseline

* allocate space for font imagery in unpacked word format - egads, this
* uses a lot of memory, buts its the price to be paid I guess?
*

            CLR.L    FontData          ;NULL by default
            CLR.L    Imagebuf

            MULU     #512,D0           ;1 WORD per line * 256 chars
            MOVE.L   D0,FontSize       ;save size of buffer
            MOVE.L   #$10003,D1        ;MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR
            MOVEA.L  $4,A6
            JSR      _LVOAllocMem(A6)  ;allocate space
            TST.L    D0
            BEQ      Initfailed        ;no memory for font data
            MOVE.L   D0,FontData       ;save pointer

* allocate an image buffer for me to draw text in

            MOVE.L   YSize,D0
            MULU     #128,D0           ;size of buffer calculated
            MOVE.L   D0,Imagesize      ;save size
            MOVEQ    #03,D1            ;MEMF_PUBLIC|MEMF_CHIP
            MOVEA.L  $4,A6
            JSR      _LVOAllocMem(A6)  ;allocate space
            TST.L    D0
            BEQ      NoImagebuf        ;no memory for font data
            MOVE.L   D0,Imagebuf       ;save pointer

* unpack font data

            MOVEA.L  tf_CharLoc(A2),A0 ;location of offsets|width
            MOVEA.L  tf_CharData(A2),A1
            MOVEA.L  FontData,A3       ;where to put unpacked imagery

            CLR.L    D0
            MOVE.B   tf_LoChar(A2),D0

            CLR.L    D1
            MOVE.B   tf_HiChar(A2),D1

            SUB.B    D0,D1             ;total # of chars to unpack

            LSL.L    #1,D0             ;BYTE to WORD offset
            ADDA.L   D0,A3             ;adjust pntr into image array now

dounpack:   MOVE.L   (A0)+,D0          ;fetch offset|width of each char

            CLR.L    D2
            MOVE.W   D0,D2             ;width in D2

            SWAP     D0                ;pix offset in D0
            CLR.L    D3
            MOVE.W   D0,D3             ;word offset in D3

            AND.L    #$000F,D0
            LSR.W    #4,D3             ;calc word offset
            LSL.W    #1,D3

            CLR.L    D4                ;create mask
            NOT.L    D4                ;all ones!
            LSR.L    D2,D4             ;mask for this character
            NOT.L    D4                ;invert mask

            MOVE.L   YSize,D5
            SUBQ.W   #1,D5             ;-1 for DBF loop
            CLR.L    D6

unpkfont:   MOVE.L   0(A1,D3.W),D7     ;create in D7

            LSL.L    D0,D7             ;left justify?
            AND.L    D4,D7             ;mask lower bits
            SWAP     D7                ;move to lower word
            
            MOVE.W   D7,0(A3,D6.L)     ;store

            ADD.W    tf_Modulo(A2),D3  ;adjust word offset
            ADD.L    #512,D6

            DBF      D5,unpkfont

            ADDQ.L   #2,A3

            DBF      D1,dounpack

* set up arrays of pre-inited masks, shift values, and target addresses

            MOVE.W   #DEST+SRCB+SRCA+$FC,D7

            MOVE.L   XSize,D0
            CMP.W    #08,D0            ;if equal to 8, use FASTEST mode!
            BNE      docon0
            MOVEQ    #00,D7            ;bltcon mask for bltcon1, or 0

docon0:

            MOVE.W   #255,D1           ;loop 256 times
            MOVEQ    #00,D0            ;initial pixel offset

            MOVEA.L  #masks,A0
            MOVEA.L  #shift,A1
            MOVEA.L  #local,A2

            MOVEQ    #12,D5            ;shift value used later
            MOVE.L   XSize,D6          ;used later

setup:      MOVE.L   D0,D2
            MOVE.L   D2,D3

            LSR.W    #4,D2             ;calculate word offset
            LSL.W    #1,D2             ; div by 16 * 2 for WORD offset

            AND.W    #$000F,D3         ;mask out all but pix offset

            MOVE.L   D2,D4
            ADD.L    Imagebuf,D4       ;address to write this too
            MOVE.L   D4,(A2)+          ;save address

            CLR.W    D4                ;create mask
            NOT.W    D4                ;all ones!
            LSR.W    D3,D4             ;mask for this character
            NOT.W    D4                ;invert mask

            MOVE.W   D4,(A0)+          ;save mask

            LSL.W    D5,D3             ;shift for bltcon format
            OR.W     D7,D3             ;depends of con0, or con1
            MOVE.W   D3,(A1)+          ;save shift

            ADD.L    D6,D0
            DBF      D1,setup

* determine maximum # of characters which can be drawn

            MOVE.L   XSize,D0
            MOVE.L   #1008,D1
            DIVU     D0,D1
            MOVE.W   D1,Maxchars

* set-up blitter control functions based on font width
* optimize for 8 bit wide fonts!

            CMP.W    #08,D0            ;if equal to 8, use FASTER mode!
            BEQ      faster

slower:     MOVE.L   #Bltslow,OutPut
            MOVEQ    #2,D0             ;width
            BRA      setsize

faster:     MOVE.L   #Bltfast,OutPut
            MOVEQ    #1,D0             ;width

setsize:    MOVE.L   YSize,D1          ;height
            LSL.W    #6,D1             ;per blitter's delight
            OR.W     D1,D0
            MOVE.L   D0,blitsize

            RTS                        ;return TRUE


* some error, return false

NoImagebuf: JSR      _FreeFastText     ;release alloced memory

* indicates regular system Text() may be used via these calls

Initfailed: CLR.L    OutPut            ;default to calling Text()
            MOVEQ    #00,D0            ;return FALSE
            RTS


* ---------------------------------------------------------------------
* Routines to render the line via the blitter!
*
* The blitter routines vary somewhat to optimize for speed!  8 bit wide
* fonts are drawn much faster then other width fonts, but all fonts
* are drawn much faster then Text()!  This makes sense to do this since
* 8 bit wide fonts are the most common, and because I can make use of
* some special blitter capabilities to speed the process along!
* ---------------------------------------------------------------------


rp          EQU      0004        ;stack offsets
txbptr      EQU      rp+4
count       EQU      txbptr+4

_FastText:  TST.L    OutPut
            BEQ      CallText    ;if InitFastText() failed!

            MOVE.L   count(SP),D3
            BEQ      Noway       ;why would you put a 0 for # of chars?
            CMP.W    Maxchars,D3
            BLS      getblitter
            MOVE.W   Maxchars,D3 ;prevent overflow

* ok, I need that blitter for me only!

getblitter: SUBQ.W   #1,D3
            JSR      _OwnBlitter
            JSR      _WaitBlit

* set-up globals first

            MOVEA.L  txbptr(SP),A0
            MOVEM.L  group,D4-D7/A1-A3

* call appropriate routine

            MOVEA.L  OutPut,A6
            JSR      (A6)

* free blitter for someone else

            JSR      _DisownBlitter

* now blast this into the rastport!

            MOVEA.L  Imagebuf,A0       ;address of bitplane
            MOVEQ    #00,D0            ;no offset
            MOVE.L   #128,D1           ;src modulo
            MOVEA.L  rp(SP),A1         ;rastport
            CLR.L    D2
            MOVE.W   rp_cp_x(A1),D2    ;x dest
            ADD.W    D4,rp_cp_x(A1)    ;modify Move() position
            CLR.L    D3
            MOVE.W   rp_cp_y(A1),D3    ;dest y
            SUB.W    Baseline,D3       ;- baseline of font
            MOVE.L   YSize,D5          ;y size
            MOVEA.L  _GfxBase,A6
            JSR      _LVOBltTemplate(A6)
Noway:      RTS


* If InitFastText() failed, Text() may still be called via the
* FastText() function.
*
* This makes use in a system which must use any size font easier to program.
*
CallText:   MOVEA.L  rp(SP),A1
            MOVEA.L  txbptr(SP),A0
            MOVE.L   count(SP),D0
            MOVEA.L  _GfxBase,A6
            JSR      _LVOText(A6)
            RTS

* --------------------------------------------------
* This is the faster logic for an 8 bit wide fonts!
* --------------------------------------------------
Bltfast:    MOVEA.L  #$dff000,A6       ;address of custom chips

* once set, these blitter registers dont change

            MOVE.W   #DEST+SRCB+SRCA+$FC,bltcon0(A6)
            MOVE.W   #$FFFF,bltalwm(A6)   ;no last word mask
            MOVE.W   #126,bltdmod(A6)
            MOVE.W   #126,bltamod(A6)
            MOVE.W   #510,bltbmod(A6)

* do as much set-up as possible while last blit is busy

blit8:      CLR.L    D0
            MOVE.B   (A0)+,D0
            BEQ      blt8done          ;terminate if NULL found

            LSL.W    #1,D0             ;cast to WORD offset
            ADD.L    D5,D0             ;ready with pointer!

            ADD.L    D6,D4             ;add to width

Wait8:      BTST     #6,dmaconr(A6)    ;wait for last blit to complete
            BNE      Wait8

* these blitter register change for each blit

            MOVE.L   D0,bltbpt(A6)     ;b src
            MOVE.L   (A3),bltdpt(A6)   ;d src pntr
            MOVE.L   (A3)+,bltapt(A6)  ;a src pntr
            MOVE.W   (A1)+,bltafwm(A6) ;first word mask           
            MOVE.W   (A2)+,bltcon1(A6) ;shift value for b

            MOVE.W   D7,bltsize(A6)    ;trigger blit
            DBF      D3,blit8          ;char counter

blt8done:   RTS

* --------------------------------------------------
* This is the slower mode for odd width fonts!
* --------------------------------------------------
Bltslow:    MOVEA.L  #$dff000,A6       ;address of custom chips
            MOVEQ    #00,D1            ;address of destination here

* these registers dont change once set

            CLR.W    bltalwm(A6)       ;last word mask
            CLR.W    bltcon1(A6)       ;no special modes
            MOVE.W   #124,bltbmod(A6)  ;modulos
            MOVE.W   #124,bltdmod(A6)

* this bit clears the image buffer as needed - speed optimized
* thinner fonts will be drawn faster due to less hits
* a hit is TRUE whenever the font imagery rolls over into the next word

doblits:    MOVE.W   (A1)+,D0
            MOVE.L   (A3)+,D2
            CMP.L    D2,D1
            BEQ      dochars           ;working on same word

Waitlast:   BTST     #6,dmaconr(A6)    ;wait if needed
            BNE      Waitlast

            MOVE.L   D2,D1             ;save for next time around

            MOVE.W   #124,bltamod(A6)
            MOVE.W   D0,bltafwm(A6)
            MOVE.L   D2,bltdpt(A6)     ;d src pntr
            MOVE.L   D2,bltapt(A6)     ;a src pntr
            MOVE.W   #DEST+SRCA+$F0,bltcon0(A6) ;d=a
            MOVE.W   D7,bltsize(A6)    ;trigger blitter clear

* setup while last blit is busy

dochars:    CLR.L    D0
            MOVE.B   (A0)+,D0
            BEQ      bltodddone        ;terminate if NULL found

            LSL.W    #1,D0             ;cast to WORD offset
            ADD.L    D5,D0             ;ready with pointer!

            ADD.L    D6,D4             ;add to width

Waitpack:   BTST     #6,dmaconr(A6)    ;wait for image packing
            BNE      Waitpack

* set up blitter for character image move

            MOVE.W   #508,bltamod(A6)
            MOVE.W   #$FFFF,bltafwm(A6)
            MOVE.L   D0,bltapt(A6)     ;a src
            MOVE.L   D2,bltbpt(A6)     ;b src pntr
            MOVE.L   D2,bltdpt(A6)     ;d src pntr
            MOVE.W   (A2)+,bltcon0(A6) ;shift value for a
            MOVE.W   D7,bltsize(A6)    ;trigger blit

            DBF      D3,doblits        ;checks count

bltodddone: RTS

            RTS


            DSEG
* global variables I use - private!

Imagebuf:   dc.l     0     ;address of image buffer - part of above struct
Imagesize:  ds.l     1     ;size of working buffer

FontSize:   ds.l     1     ;size of font data buffer

YSize:      ds.l     1     ;size of font height

Maxchars:   ds.w     1     ;Max chars which can be drawn at one time

Baseline:   ds.w     1     ;baseline of font

OutPut:     dc.l     0     ;address of function to call or NULL for Text()

masks:      ds.w     256   ;256 words for masks
shift:      ds.w     256   ;256 shift values
local:      ds.l     256   ;256 pointers to target location

* these are grouped for a good reason - the MOVEM instruction is used
* by the rendering routines for efficiency - DONT play with the order
* of these unless you know what you are doing.

group:      dc.l     0     ;0 to init width of line register
FontData:   dc.l     0     ;address of font data
XSize:      dc.l     0     ;size of font width
blitsize:   dc.l     0     ;blit size value
            dc.l     masks ;address of arrays
            dc.l     shift
            dc.l     local


            END

SHAR_EOF
cat << \SHAR_EOF > FastText.doc
FastText revision 3.0 Copyright 1988 by Darren M. Greenwald

FastText is a copyrighted program.  It may be distributed freely, but it
may NOT be sold/included in any way in any commercial, or shareware
ventures without permission from the author.  It may be distributed in
other public domain works so long as a notice of credit appears in the
documentation.

FastText may be distributed as part of a public domain collection, and
posted on telecommunication services so long as no additional charge is
made above, and beyond the normal, and reasonable fees charged for
the media, or use of system time.

If you would like permission to use this program in a commercial, or
shareware venture, I can be contacted via the following methods:

On GEnie:               Send E-MAIL to DMG
On Cute (714) 532-5698: Post a message in any forum to Darren Greenwald
At Home:                (714) 545-6458

Including FastText in your programs -

FastText is written in assembly using the Manx Assembler.  Any changes
needed to assemble this file with other assemblers is left up to you. 
You need then only link the resulting object file with your code, and
replace all calls too Text() with FastText().  In addition you must call the
InitFastText() routine before calling FastText(), and finally call
FreeFastText() as part of your cleanup/exit routine(s).  See the included
FastText demo (Ftest.c) for an example of how easy this is to use.

In "C" format, the calls are defined like so:

InitFastText
------------

success=InitFastText(Font)

Inputs: Font - pointer to a TextFont structure

Return: TRUE, or FALSE

Description:

This routine does a number of things for you.  It checks to make sure that
the font is a non-proportional font; it also checks to make sure the font
is no less then 4 bits wide, but no more then 16 bits.  In any other case
this routine returns FALSE.  Should this routine fail, you need not concern
yourself too much.  In this case all calls to FastText() are automatically
routed to call Text() instead.

Two CHIP RAM buffers are allocated based on the fonts height.  Fonts can be
any height, but keep in mind that taller fonts use more memory.  One chip
ram buffer is allocated for use as a buffer to draw the text imagery in, and
the other is used to store the unpacked font data.

The font image data buffer requires 512 bytes * the font height.

The drawing buffer requires 128 bytes * the font height.

If this seems like a lot of memory, this is the trade off you make for the
faster text rendering.  If the memory cannot be allocated, this routine
will return FALSE, and all calls to FastText() are routed to call Text()
instead.

Finally this routine upacks the font data, sets up the masks, blitter shift
values, and some pointers to the image buffer.  Precalculating this
stuff means that these calculations do not have to be done each time a line
of text is rendered.

A special faster blitter routine is used for 8 bit wide fonts because 1.)
Due to the way the blitter handles shifting it is possible to draw 8 bit
wide fonts faster, and 2.) This works out well since 8 bit wide fonts are
commonly used as the system font.

This routine should be called as part of your programs initialization
procedures - it is your option to check for a return value since even if
this fails, all calls to FastText() will automatically call Text() instead.
This routine executes lickety-split; you won't have to wait "a moment" for
the unpacking, and set-up to complete.

FastText
--------

FastText(p,string,length)

Inputs: rp       - pointer to a rastport structure
        string   - pointer to a string
        length   - length of string to draw

Return: None

Description:

This call is very similar to Text().  It uses the exact same parameters
as Text(), and behaves in a very similar manner.  You can set drawing
colors (via SetAPen(), SetBPen()), drawing modes, etc.  The text position
is set via the Move() function just like Text().

The X drawing position in the rastport is automatically incremented by the
length (in pixels) of the string of text.

There are also some significant differences (speed of rendering included)!

Unlike Text() which draws a special image for non-defined characters in a
font, FastText() draws undefined characters as blank spaces.  This could be
changed if it causes anyone any problems.  I prefer it this way, but
perhaps you may not?

FastText() does not currently support any font styles (e.g., bold,
underline, italics).  This may be changed in the future.

The REVPATH flag is ignored.

FastText() treats NULL's as End of Line characters regardless of the length
of string parameter.  This behavior can be changed if it causes anyone any
problems.  I like it this way, but you may not.  Yes, this was intentional
since it means I can call FastText(), and set the count to some large
number rather then having to calculate the length of each string.  Text()
on the other hand is terminated only by the length parameter, and will
print NULL's as a non-printable character (usually a BOXY looking image).


FreeFastText
------------

FreeFastText()

Inputs: None

Return: None

Description:

Frees memory allocated by InitFastText().  This routine can be called
safely even if InitFastText() failed - in other words, it won't try to free
memory which was never allocated.

----------------------------------------------------------------------

Other notes:

It is very likely that this code is less then perfect.  Let the bug reports
roll in!  Let me know, and I'll try to fix it ASAP.  Also hopefully I can
further optimize the speed of the rendering routines.  In the future this
whole thing may change anyway so that multiple fonts can be opened at the
same time.SHAR_EOF
cat << \SHAR_EOF > Ftest.c
/*
 * FastText() text demo by Darren M. Greenwald
 * Copyright 1987 - FastText() REV 3.0
 *
 * "C" example of use.
 * 
 * You MUST assemble, and link in the FastText file in order for this to
 * work!!!
 * 
 * Note that all work was done using Manx 3.6
 * I leave it up to you to make adjustments as needed to work with your
 * compiler/assembler.
 *
 * TURN OFF any text speed up programs if you really want to test this
 * program right.  Programs such BLITZFONTS, and MicroSmith's FastFonts
 * only speed up 8 bit wide fonts.  These routines allow you to gain
 * a significant speed up for all size fonts, and the most speed up for
 * 8 bit wide fonts.  Font widths other then 8 bits wide will vary in
 * speed.  Thinner fonts will be drawn more quickly then wider fonts, but
 * you can rest assured that the FastText() routines draw text faster then
 * Text() - generally MUCH faster.
 *
 * If the font cannot be drawn faster (e.g., too wide, too thin, PROP
 * font), then Text() is automatically called.
 * 
 */

#include <exec/types.h>
#include <intuition/intuition.h>
#include <exec/memory.h>

#define REV 0L
#define SIZE 640L

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct Window *Window = NULL;
struct RastPort *rp;
struct Window *OpenWindow();
void *OpenLibrary();

struct NewWindow NewWindow =
   { 0,0,640,200,0,1,
     CLOSEWINDOW,ACTIVATE|BORDERLESS|WINDOWDEPTH|WINDOWCLOSE|SMART_REFRESH,
     NULL,NULL,
     (UBYTE *)"FastText Demo Rev 3.0 - Close me!",
     NULL,NULL,0,0,0,0,WBENCHSCREEN
   };

void Cleanup();


void main()
{

ULONG MaxRows,fonthght,pixrow,i,j;

   IntuitionBase = (struct IntuitionBase *)
      OpenLibrary("intuition.library",REV);
   if(IntuitionBase == NULL) Cleanup();

   GfxBase = (struct GfxBase *)
      OpenLibrary("graphics.library",REV);
   if(GfxBase == NULL) Cleanup();

   Window = (struct Window *)
      OpenWindow(&NewWindow);
   if(Window == NULL) Cleanup();

   rp = Window->RPort;


/*
 * Wait till the close us down cause we are to lazy to mess with gadgets,
 * or menus!
 */

   Wait(1L<<Window->UserPort->mp_SigBit);

   SetAPen(rp,1L);
   SetBPen(rp,0L);

   InitFastText(rp->Font); /* You could check for a TRUE/FALSE return */
   
      pixrow=32L;

      fonthght=(ULONG)rp->Font->tf_YSize;
      MaxRows=(Window->Height-pixrow)/fonthght;

      SetWindowTitles(Window,"Drawing via Text()",NULL);

      for(i=1;i<MaxRows;i++)  /* do maximum # of times possible */
      {
         for(j=1;j<200;j++)   /* redraw line 300 times per row */
         {
            Move(rp,j+4L,pixrow);
            Text(rp," This is 36 characters of SLOW text!",36L);
         }
         pixrow+=fonthght;
      }

dox:  pixrow=32L;

      SetWindowTitles(Window,"Drawing via FastText()",NULL);

      for(i=1;i<MaxRows;i++)  /* do maximum # of times possible */
      {
         for(j=1;j<200;j++)   /* redraw line 300 times per row */
         {
            Move(rp,j+4L,pixrow);
            FastText(rp," This is 36 characters of FAST text!",36L);
         }
         pixrow+=fonthght;
      }


   Cleanup();
}

void Cleanup()
{
   FreeFastText();

   if(Window)           CloseWindow(Window);

   if(GfxBase)          CloseLibrary(GfxBase);
   if(IntuitionBase)    CloseLibrary(IntuitionBase);

   exit(0L);
}


SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.