QuickDraw/DrawText.a

934 lines
46 KiB
Plaintext
Executable File

.INCLUDE GRAFTYPES.TEXT
;--------------------------------------------------------------
;
; --> DRAWTEXT.TEXT
;
; QuickDraw Character Generator
;
; Completely reworked 29 Apr 85 by Bill Atkinson to get 50% speed up.
; Takes advantage of optional height table at end of font.
;
.PROC DrText,4
.REF RightMask,MaskTab,RSect,ShieldCursor,ShowCursor
.REF StdTxMeas,RectInRgn,MapRect,StretchBits,TrimRect
;------------------------------------------------------------
;
; PROCEDURE DrText(count: INTEGER; textAddr: Ptr; numer,denom: Point);
;
; DRAWS CHARACTERS INTO THE CURRENT PORT'S BITMAP.
; THE FONT AND ATTRIBUTES ARE GIVEN IN THE CURRENT PORT'S CHARSTYLE.
;
;-------------------------------------------
;
; KERNED STRIKE FONT FORMAT OFFSETS:
;
FORMAT .EQU 0 ;WORD
MINCHAR .EQU 2 ;WORD
MAXCHAR .EQU 4 ;WORD
MAXWD .EQU 6 ;WORD
FBBOX .EQU 8 ;WORD
FBBOY .EQU 10 ;WORD
FBBDX .EQU 12 ;WORD
FBBDY .EQU 14 ;WORD
LENGTH .EQU 16 ;WORD
ASCENT .EQU 18 ;WORD
DESCENT .EQU 20 ;WORD
XOFFSET .EQU 22 ;WORD
RASTER .EQU 24 ;WORD
;------------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 14 ;SIZE OF PARAMETERS
COUNT .EQU PARAMSIZE+8-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG
NUMER .EQU TEXTADDR-4 ;LONG, POINT
DENOM .EQU NUMER-4 ;LONG, POINT
;-----------------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
SAVESTK .EQU -4 ;LONG
TEXTRECT .EQU SAVESTK-8 ;RECT
TEXTR2 .EQU TEXTRECT-8 ;RECT
MINRECT .EQU TEXTR2-8 ;RECT
BUFEND .EQU MINRECT-4 ;LONG
BUFSTART .EQU BUFEND-4 ;LONG
BUFSIZE .EQU BUFSTART-2 ;WORD
BUFROW .EQU BUFSIZE-2 ;WORD
BUFLEFT .EQU BUFROW-2 ;WORD
BUF2START .EQU BUFLEFT-4 ;LONG
BUF2END .EQU BUF2START-4 ;LONG
HEIGHT .EQU BUF2END-2 ;WORD
SRCBITS .EQU HEIGHT-14 ;BITMAP
DSTBITS .EQU SRCBITS-14 ;BITMAP
FAKERGN .EQU DSTBITS-10 ;RECTANGULAR REGION
FAKEPTR .EQU FAKERGN-4 ;LONG, FAKE MASTER POINTER
SRCADDR .EQU FAKEPTR-4 ;LONG
SRCROW .EQU SRCADDR-2 ;WORD
FASTFLAG .EQU SRCROW-2 ;BYTE
PENLOC .EQU FASTFLAG-4 ;POINT
SRCPTR .EQU PENLOC-4 ;LONG
DSTPTR .EQU SRCPTR-4 ;LONG
STRETCH .EQU DSTPTR-2 ;BOOLEAN
FROMRECT .EQU STRETCH-8 ;RECT
TORECT .EQU FROMRECT-8 ;RECT
SRCRECT .EQU TORECT-8 ;RECT
DSTRECT .EQU SRCRECT-8 ;RECT
SPWIDTH .EQU DSTRECT-4 ;FIXED POINT
CHARLOC .EQU SPWIDTH-4 ;FIXED POINT
INFO .EQU CHARLOC-8 ;4 WORDS
HEIGHTAB .EQU INFO-4 ;LONG
WIDTAB .EQU HEIGHTAB-4 ;LONG
LOCTAB .EQU WIDTAB-4 ;LONG
TOPHT .EQU LOCTAB-2 ;word
HEIGHTFLAG .EQU TOPHT-2 ;byte
MAXMIN .EQU HEIGHTFLAG-2 ;word
MINCH .EQU MAXMIN-2 ;word
SAVEA5 .EQU MINCH-4 ;LONG
NUMER2 .EQU SAVEA5-4 ;Point
DENOM2 .EQU NUMER2-4 ;Point
VARSIZE .EQU DENOM2 ;SIZE OF VARIABLES
LINK A6,#VARSIZE ;ALLOCATE TEMP VARS
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER WHERE STACK WAS
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;GET CURRENT GRAFPORT
MOVE.L NUMER(A6),NUMER2(A6) ;SAVE ORIGINAL NUMER
MOVE.L DENOM(A6),DENOM2(A6) ;SAVE ORIGINAL DENOM
;
; Call StdTxMeas to swap font and measure width.
;
CLR -(SP) ;ROOM FOR FCN RESULT
MOVE COUNT(A6),-(SP) ;PUSH COUNT
BLE GOHOME ;QUIT IF COUNT <= 0
;STACK CLEANED UP BY SAVESTK
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
PEA NUMER(A6) ;PUSH VAR NUMER
PEA DENOM(A6) ;PUSH VAR DENOM
PEA INFO(A6) ;PUSH VAR INFO
JSR StdTxMeas ;MEASURE TEXT
MOVE (SP)+,D1 ;POP UNSCALED WIDTH RESULT
;
; StdTxMeas also stashes FMOutPtr in QD global FONTPTR,
; and unscaled fixed point text width inn FixTxWid.
;
MOVE.L FONTPTR(A4),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE FBBDY(A2),TOPHT(A6) ;INIT TOPHT IN CASE OLD FONT
BTST #0,1(A2) ;DOES FONT HAVE HEIGHT TABLE ?
SNE HEIGHTFLAG(A6) ;REMEMBER FOR LATER
;
; Setup textRect, the rectangle bounding the entire string.
;
MOVE.L PNLOC(A3),D2 ;GET PEN LOCATION
MOVE.L D2,PENLOC(A6) ;SAVE FOR LATER
MOVE.W D2,TEXTRECT+LEFT(A6) ;TEXTRECT.LEFT := PNLOC.H
ADD.W D1,D2 ;right := left + width
MOVEQ #7,D0 ;get mode mask
AND TXMODE(A3),D0 ;is txMode = srcCopy ?
BEQ.S NOSLOP ;yes, don't add slop
CMP #3,D0 ;is textMode > srcBic ?
BGT.S NOSLOP ;yes, don't add slop
ADD.W #32,D2 ;SLOP FOR ITALIC,BOLD,OVERSTRIKE
NOSLOP MOVE.W D2,TEXTRECT+RIGHT(A6) ;STORE IN TEXTRECT.RIGHT
SWAP D2 ;GET PNLOC.V
SUB ASCENT(A2),D2 ;SUBTRACT ASCENT
MOVE D2,TEXTRECT+TOP(A6) ;TEXTRECT.TOP := PNLOC.V - ASCENT
ADD FBBDY(A2),D2 ;ADD HEIGHT
MOVE D2,TEXTRECT+BOTTOM(A6) ;TEXTRECT.BOTTOM := TOP + HEIGHT
MOVE.L TEXTRECT(A6),TEXTR2(A6) ;MAKE AN EXTRA COPY
MOVE.L TEXTRECT+4(A6),TEXTR2+4(A6) ;OF TEXTRECT IN TEXTR2
;
; Check for stretching
;
MOVE.L NUMER(A6),D0 ;GET NUMERATOR
CMP.L DENOM(A6),D0 ;ARE WE STRETCHING ?
SNE STRETCH(A6) ;REMEMBER THE ANSWER
BEQ.S NOSTRCH ;CONTINUE IF NOT STRETCHING
;
; We will be stretching. Setup fromRect and toRect and map textR2.
;
MULU D0,D1 ;MULT WIDTH BY NUMER.H
DIVU DENOM+H(A6),D1 ;DIV BY DENOM.H
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,TORECT+TOPLEFT(A6) ;SET UP TORECT TOPLEFT
ADD.W NUMER+H(A6),D0 ;CALC PENLOC.H + NUMER.H
MOVE D0,TORECT+RIGHT(A6) ;SET UP TORECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD NUMER+V(A6),D0 ;CALC PENLOC.V + NUMER.V
MOVE D0,TORECT+BOTTOM(A6) ;SET UP TORECT BOTTOM
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,FROMRECT+TOPLEFT(A6) ;SET UP FROMRECT TOPLEFT
ADD.W DENOM+H(A6),D0 ;CALC PENLOC.H + DENOM.H
MOVE D0,FROMRECT+RIGHT(A6) ;SET UP FROMRECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD DENOM+V(A6),D0 ;CALC PENLOC.V + DENOM.V
MOVE D0,FROMRECT+BOTTOM(A6) ;SET UP FROMRECT BOTTOM
PEA TEXTR2(A6) ;PUSH TEXTR2
PEA FROMRECT(A6) ;PUSH FROMRECT
PEA TORECT(A6) ;PUSH TORECT
JSR MAPRECT ;MAP TEXTR2 (PRESERVES ALL REGS)
NOSTRCH ADD D1,PNLOC+H(A3) ;BUMP PEN BY (SCALED) TEXT WIDTH
;
; Quit if the pen is hidden
;
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT GOHOME ;YES, QUIT
;
; Calc minRect: the intersection of textRect, bitMap bounds,
; clipRgn and visRgn bounding boxes. Quit if no intersection.
;
PEA TEXTR2(A6) ;PUSH (MAPPED) TEXTRECT
PEA PORTBOUNDS(A3) ;PUSH BITMAP BOUNDS
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
MOVE #4,-(SP) ;PUSH NRECTS=4
PEA MINRECT(A6) ;PUSH DST ADDR
JSR RSECT ;CALC INTERSECTION
BEQ GOHOME ;QUIT IF NO INTERSECTION
;
; Set up srcAddr, srcRow, and height
;
LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE.L A0,SRCADDR(A6) ;SAVE FOR LATER
MOVE RASTER(A2),D1 ;GET WORDS PER ROW IN FONT
ADD D1,D1 ;DOUBLE FOR BYTES PER ROW
MOVE D1,SRCROW(A6) ;REMEMBER FOR LATER
MOVE FBBDY(A2),HEIGHT(A6) ;SETUP HEIGHT FOR LATER
;
; Test for fast case:
; not stretched, no color mapping, txMode = srcOr,
; not bold, italic, underlined, outlined or shadowed,
; visRgn and clipRgn both rectangular.
;
TST.W 6(A4) ;TEST BOLD AND ITALIC
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
CMP #1,TXMODE(A3) ;IS TEXT MODE SRCOR ?
BNE NOTFAST ;NO, NOT FAST
TST.W 10(A4) ;TEST ULTHICK AND SHADOW
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B STRETCH(A6) ;IS TEXT STRETCHED ?
BNE NOTFAST ;YES, NOT FAST
MOVE COLRBIT(A3),D1 ;ARE WE COLOR MAPPING ?
BEQ.S NOCOLOR ;NO, CONTINUE
MOVE.L BKCOLOR(A3),D0 ;YES GET BACKGROUND COLOR
NOT.L D0 ;INVERT IT
AND.L FGCOLOR(A3),D0 ;AND WITH FOREGROUND COLOR
BTST D1,D0 ;IS THAT PLANE NORMAL ?
BEQ NOTFAST ;NO, NOT FAST
NOCOLOR MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
MOVEQ #10,D0
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
BNE.S NOTFAST ;NO, NOT FAST
MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE
MOVE.L (A1),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D0 ;IS VISRGN RECTANGULAR ?
BEQ.S FAST ;YES, TAKE FAST OPTIMIZATION
;
; All systems go except for VisRgn not rectangular.
; Check if visRgn sect minRect is rectangular.
; IF TrimRect(visRgn,minRect) THEN take the fast way.
;
MOVE.L A1,-(SP) ;PUSH VISRGN
PEA MINRECT(A6) ;PUSH MINRECT
JSR TRIMRECT ;CALL TRIMRECT
BLT GOHOME ;quit if intersection empty
BGT.S NOTFAST ;continue if non-rectangular
;
; Fast case, go directly to screen.
; If text is clipped vertically, then clear heightflag and update TOPHT
;
FAST ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT.TOP
MOVE MINRECT+BOTTOM(A6),D1 ;GET MINRECT.BOTTOM
SUB TEXTRECT+TOP(A6),D0 ;was top clipped ?
BNE.S VCLIP ;yes, handle clip
CMP TEXTRECT+BOTTOM(A6),D1 ;was bottom clipped ?
BEQ.S VCLIPOK ;no, continue
VCLIP CLR.B HEIGHTFLAG(A6) ;can't use height table
MOVE.B D0,TOPHT(A6) ;use adjusted top
SUB MINRECT+TOP(A6),D1 ;calc clipped height
MOVE.B D1,TOPHT+1(A6) ;replace TOPHT
VCLIPOK MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
SUB PORTBOUNDS+TOP(A3),D0 ;CONVERT TO GLOBAL COORDINATES
MULU PORTBITS+ROWBYTES(A3),D0 ;MULT BY ROWBYTES
ADD.L PORTBITS+BASEADDR(A3),D0 ;ADD START OF DST BITMAP
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
MOVE PORTBITS+ROWBYTES(A3),BUFROW(A6) ;SET UP BUFROW FOR LATER
MOVE PORTBOUNDS+LEFT(A3),BUFLEFT(A6) ;REMEMBER BUFLEFT
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L PORTBOUNDS+TOPLEFT(A3),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
JSR SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
BRA GETPTRS
;
; Slow case: Setup for an off-screen buffer.
;
; Calc bufLeft: (word-align to avoid shift)
;
NOTFAST CLR.B FASTFLAG(A6) ;NOT GOING DIRECTLY TO SCREEN
MOVE TEXTRECT+LEFT(A6),D0 ;GET TEXTRECT LEFT
SUB PORTBOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL
AND #$FFF0,D0 ;TRUNC TO WORD BOUND
SUB #32,D0 ;32 DOT SLOP FOR SLANT & SHADOW
ADD PORTBOUNDS+LEFT(A3),D0 ;RETURN TO LOCAL COORDS
MOVE D0,BUFLEFT(A6) ;REMEMBER FOR LATER
;
; Calculate buffer size
;
MOVE TEXTRECT+RIGHT(A6),D1 ;BUFRIGHT := TEXTRECT RIGHT
SUB D0,D1 ;WIDTH:=BUFRIGHT-BUFLEFT
LSR #5,D1 ;CONVERT DOTS TO LONGS
ADD #2,D1 ;ROUND UP PLUS EXTRA LONG
MOVE HEIGHT(A6),D3 ;GET HEIGHT
MULU D1,D3 ;BUFSIZE:=HEIGHT*BUFROW LONGS
MOVE D3,BUFSIZE(A6) ;SAVE FOR LATER
LSL #2,D1 ;QUAD BUFROW FOR BYTES
MOVE D1,BUFROW(A6) ;SAVE FOR LATER
;
; Calculate total stack requirements for off-screen buffers.
;
MOVE.L D3,D2 ;GET BUFSIZE LONGS
TST.B 11(A4) ;ARE WE SHADOWING ?
BEQ @1 ;NO, CONTINUE
ADD.L D2,D2 ;YES, CALC 2*BUFSIZE
EXT.L D1 ;SIGN EXTEND BUFROW
ADD.L D1,D2 ;CALC TOTAL LONGS
@1 LSL.L #2,D2 ;CALC TOTAL STACK BYTES NEEDED
ADD.L #1024,D2 ;ADD 1 KBYTE SLOP
;
; If stack is too small to allocate buffer(s), then recursively call
; DrText with the left half and the right half of the text string.
;
_StackAvail ;Get StackAvail IN D0
CMP.L D0,D2 ;IS stackNeeded > stackAvail ?
BLE.S STACKOK ;NO, CONTINUE
MOVE.L PENLOC+H(A6),PNLOC+H(A3) ;RESTORE PNLOC TO ORIGINAL
MOVE COUNT(A6),D7 ;GET CHARACTER COUNT
LSR #1,D7 ;DIVIDE IN HALF
BEQ GOHOME ;GIVE UP IF COUNT WAS ONLY ONE
MOVE D7,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR DrText ;DRAW THE FIRST HALF
MOVE COUNT(A6),D0 ;GET ORIGINAL CHARACTER COUNT
SUB D7,D0 ;SUBTRACT CHARS ALREADY DONE
MOVE D0,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),A0 ;GET ORIGINAL TEXTADDR
ADD D7,A0 ;BUMP PAST CHARS ALREADY DONE
MOVE.L A0,-(SP) ;PUSH NEW TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR DrText ;DRAW THE SECOND HALF
BRA GOHOME ;AND QUIT !
;
; Allocate and clear an off-screen buffer
;
STACKOK SUB #1,D3 ;INIT DBRA LOOP COUNT
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
CLRLOOP CLR.L -(SP)
DBRA D3,CLRLOOP ;ALLOCATE AND CLEAR BUFFER
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
;
; Get pointers to location table, width table, and height table in font
;
GETPTRS LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE FBBDY(A2),D0 ;GET HEIGHT OF FONT BITMAP
MULU SRCROW(A6),D0 ;CALC TOTAL SIZE OF STRIKE
ADD.L D0,A0 ;A1 := START OF LOC TABLE
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
CLR.L D0 ;get ready for unsigned word
MOVE LENGTH(A2),D0 ;HOW MANY WORDS IN STRIKE BODY
ADD.L D0,D0 ;DOUBLE FOR BYTECOUNT
LEA 16(A2,D0.L),A1 ;GET START OF WIDTH TABLE
MOVE.L A1,WIDTAB(A6) ;SAVE FOR LATER
MOVE MAXCHAR(A2),D0 ;GET MAXCHAR
MOVE MINCHAR(A2),D1 ;GET MINCHAR
MOVE D1,MINCH(A6) ;STASH MINCHAR FOR LATER
SUB D1,D0 ;CALC MAXCHAR-MINCHAR
MOVE D0,MAXMIN(A6) ;SAVE FOR LATER
ADD #3,D0 ;CALC MAXMIN+3
ADD D0,D0 ;CALC 2*(MAX-MIN+3)
BTST #1,1(A2) ;DOES FONT HAVE WIDTH TABLE ?
BEQ.S NOWID ;NO, CONTINUE
ADD D0,D0 ;YES, SKIP OVER WIDTH TABLE
NOWID LEA 0(A1,D0),A0 ;POINT TO HEIGHT TABLE
MOVE.L A0,HEIGHTAB(A6) ;SAVE FOR LATER
;
; Set up space width
;
MOVE.L widthPtr,A0 ;point to width table
MOVE.L 128(A0),SPWIDTH(A6) ;get width of the space char
;
; Setup misc stuff in registers for speed
;
MOVE BUFLEFT(A6),D1 ;GET BUFLEFT
MOVE PENLOC+H(A6),D0 ;GET PEN LOCATION
ADD FBBOX(A2),D0 ;ADJUST FOR KERNING
SUB D1,D0 ;MAKE CHARLOC RELATIVE TO BUFLEFT
MOVE.W D0,CHARLOC(A6) ;INIT INT PART OF CHARLOC
MOVE #$8000,CHARLOC+2(A6) ;SET FRACT PART TO ONE HALF
SUB D1,MINRECT+LEFT(A6) ;MAKE MINRECT.LEFT AND
SUB D1,MINRECT+RIGHT(A6) ;MINRECT.RIGHT BUFFER RELATIVE
MOVE.L TEXTADDR(A6),A1 ;GET TEXTPTR
BRA.S NEXTCH ;GO TO LOOP START
;---------------------------------------------------
;
; Here's the main character drawing loop:
;
SPACECH MOVE.L SPWIDTH(A6),D1 ;GET SPACE WIDTH
ADD.L D1,CHARLOC(A6) ;BUMP CHARLOC
SKIPCH SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BLE STRDONE ;QUIT IF CHARCOUNT <= 0
NEXTCH CLR D0 ;get ready for byte
MOVE.B (A1)+,D0 ;GET NEXT CHAR
CMP.B #32,D0 ;IS IT A SPACE ?
BEQ SPACECH ;YES, HANDLE IT
MOVE.L WidthPtr,A0 ;POINT TO WIDTH TABLE
MOVE D0,D4 ;COPY CHARACTER
LSL #2,D4 ;QUAD FOR TABLE OFFSET
MOVE.L 0(A0,D4),D4 ;GET FIXED POINT WIDTH
SUB MINCH(A6),D0 ;SUBTRACT SAVED MINCHAR
CMP MAXMIN(A6),D0 ;IS CH BETWEEN MINCHAR AND MAXCHAR ?
BLS.S OKCHAR ;YES, CONTINUE
MISSING MOVE MAXMIN(A6),D0 ;NO, USE MISSING SYMBOL
ADD #1,D0 ;WHICH IS ONE PAST MAXCHAR
ADD D0,D0 ;INDEX := 2*(MISSING-MINCHAR)
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0),D3 ;GET OFFSET AND WIDTH BYTES
BPL.S NOTMISS ;IS MISSING CHAR MISSING ?
BRA NEXTCH ;YES, SKIP THIS CHAR
OKCHAR ADD D0,D0 ;INDEX := 2*(ASCII-MINCHAR)
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0),D3 ;GET OFFSET AND WIDTH BYTES
BMI MISSING ;OFFSET NEG = MISSING CHAR
NOTMISS LSR #8,D3 ;GET OFFSET BYTE
ADD.W CHARLOC(A6),D3 ;DSTLEFT := CHARLOC.INT + OFFSET
ADD.L D4,CHARLOC(A6) ;ADD FIXED POINT WIDTH TO CHARLOC
MOVE.L LOCTAB(A6),A0 ;POINT TO LOCATION TABLE
MOVE 0(A0,D0),D1 ;GET SRCLEFT
MOVE 2(A0,D0),D2 ;GET SRCRIGHT
SUB D1,D2 ;CALC WIDTH OF BITS
BLE SKIPCH ;SKIP CHARBLT IF WIDTH <= 0
ADD D3,D2 ;DSTRIGHT := DSTLEFT + WIDTH
TST.B HEIGHTFLAG(A6) ;does font have height table ?
BEQ.S NOHEIGHT ;no, continue
MOVE.L HEIGHTAB(A6),A0 ;get height table
MOVE 0(A0,D0),TOPHT(A6) ;get this char's top and height
NOHEIGHT
;-----------------------------------------------------------------------
;
; Horizontal clip only if FastFlag: (else stretch,outline,shadow,italic die)
;
; skip if hidden on left, string done if hidden on right.
;
; at this point: D1: srcLeft
; D2: dstRight
; D3: dstLeft
;
TST.B FastFlag(A6) ;ARE WE GOING FAST ?
BEQ.S HORIZOK ;NO, DON'T CLIP
CMP MINRECT+LEFT(A6),D3 ;IS DSTLEFT < MINRECT.LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
CMP MINRECT+LEFT(A6),D2 ;IS DSTRIGHT <= MINRECT.LEFT ?
BLE SKIPCH ;YES, SKIP THIS CHAR
TRIMLFT MOVE MINRECT+LEFT(A6),D0 ;NO, GET MINRECT.LEFT
SUB D3,D0 ;DISCARD:=MINRECT.LEFT-DSTLEFT
ADD D0,D1 ;SRCLEFT:=SRCLEFT+DISCARD
ADD D0,D3 ;DSTLEFT:=DSTLEFT+DISCARD
CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT > MINRECT.RIGHT ?
BLE.S HORIZOK ;NO, CONTINUE
BRA.S TRIMRT ;YES, TRIM RIGHT
LEFTOK CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT <= MINRECT.RIGHT ?
BLE.S HORIZOK ;YES, CONTINUE
CMP MINRECT+RIGHT(A6),D3 ;IS DSTLEFT >= MINRECT.RIGHT ?
BGE STRDONE ;YES, IGNORE REST OF STRING
TRIMRT MOVE MINRECT+RIGHT(A6),D2 ;NO, TRIM DSTRIGHT
HORIZOK
;--------------------------------------------------------------
;
; Inputs to local block CharBlt:
;
; srcAddr(A6)
; srcRow(A6)
; bufStart(A6) = dstAddr
; bufRow(A6) = dstRow
; D1 = srcLeft
; D2 = dstRight relative to buffer, > dstLeft
; D3 = dstLeft relative to buffer
; TOPHT(A6) top and height
;
; CLOBBERS: D0,D1,D2,D3,D4,D5,D6,D7,A0,A2,A3,A4,A5
; PRESERVES: A1,A6,A7
;
;
; Setup shift count in D5 (relative shift between src and dst)
;
MOVE D3,D5 ;COPY DSTLEFT
SUB D1,D5 ;SUB SRC LEFT
MOVEQ #$F,D0 ;get a 4 bit mask
AND D0,D5 ;SHIFTCNT:=DELTA HORIZ MOD 16
;
; Setup srcAddr in A4, address of leftmost word
;
MOVE.L SRCADDR(A6),A4 ;GET START OF SRC BITMAP
ADD D5,D1 ;CALC SRCLEFT+SHIFTCNT
ASR #4,D1 ;CONVERT FROM DOTS TO WORDS
ADD D1,D1 ;DOUBLE FOR BYTES
SUB #2,D1 ;BACK UP 1 WORD SINCE PICKING UP LONG
ADD D1,A4 ;LEAVE SRCPTR IN A4
;
; Setup dstPtr in A5, address of leftmost dst word
;
MOVE.L BUFSTART(A6),A5 ;GET START OF DST BITMAP
MOVE D3,D1 ;GET A COPY OF DSTLEFT
ASR #4,D1 ;CONVERT FROM DOTS TO WORDS
ADD D1,A5 ;ADD TO DSTPTR
ADD D1,A5 ;TWICE FOR BYTES
;
; Setup leftMask in D3 and rightMask in D4
;
LEA MaskTab,A0 ;point to mask table
AND D0,D3 ;get bottom 4 bits of dstLeft
ADD D3,D3 ;double for table index
MOVE 0(A0,D3),D3 ;get mask word from table
NOT D3 ;invert it for leftMask
MOVE D2,D6 ;copy dstRight
AND D0,D2 ;get bottom 4 bits of dstRight
ADD D2,D2 ;double for table index
MOVE 0(A0,D2),D4 ;get rightMask from table
;
; Get srcRow, dstRow, and char height into regs
;
MOVE SRCROW(A6),A2
MOVE BUFROW(A6),A3
MOVE.W #255,D7 ;GET -1 BYTE, CLEAR HI BYTE
ADD.B TOPHT+1(A6),D7 ;CALC HEIGHT-1 FOR DBRA LOOP
BMI SKIPCH ;OOPS HEIGHT WAS ZERO !
;
; Adjust srcPtr and dstPtr for charTop
;
CLR.W D0 ;get ready for byte
MOVE.B TOPHT(A6),D0 ;get char top
MOVE A2,D2 ;get srcRow in D-reg
MULU D0,D2 ;calc charTop * srcRow
ADD.L D2,A4 ;add to srcPtr
MOVE A3,D2 ;get dstRow in D-reg
MULU D0,D2 ;calc charTop * dstRow
ADD.L D2,A5 ;add to dstPtr
;
; Branch based on total number of dst words
;
ASR #4,D6 ;CALC (DSTRIGHT) DIV 16
SUB D1,D6 ;CALC TOTAL NUMBER OF WORDS-1
BEQ.S WORD1 ;BR IF DST ALL IN ONE WORD
SUB #1,D6
BEQ.S LONG1 ;BR IF DST ALL IN ONE LONG
ADD #1,D7 ;COMPENSATE FOR EXTRA DBRA
BRA.S WIDE1 ;DST WIDER THAN ONE LONG
;
; Slow loop only taken in wierd cases where dst wider than a long.
;
MAIN1 MOVE.L (A4),D0 ;GET SRC FROM BITMAP
ADD #2,A4 ;BUMP SRCPTR RIGHT
LSR.L D5,D0 ;ALIGN TO DST
AND D1,D0 ;MASK EXTRA TO ZEROS
OR D0,(A5)+ ;OR SRC INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
DBRA D2,MAIN1 ;LOOP TILL LAST WORD
MOVE.L (A4),D0 ;GET SRC FROM BITMAP
LSR.L D5,D0 ;ALIGN TO DST
AND D4,D0 ;MASK WITH RIGHTMASK
OR D0,(A5) ;OR SRC INTO DST
MOVE.L SRCPTR(A6),A4 ;RESTORE SRCPTR TO LEFT
ADD A2,A4 ;BUMP TO NEXT ROW
MOVE.L DSTPTR(A6),A5 ;RESTORE DSTPTR TO LEFT
ADD A3,A5 ;BUMP DST TO NEXT ROW
WIDE1 MOVE.L A4,SRCPTR(A6) ;REMEMBER SRCPTR AT LEFT
MOVE.L A5,DSTPTR(A6) ;REMEMBER DSTPTR AT LEFT
MOVE D3,D1 ;MASK:=LEFTMASK
MOVE D6,D2 ;GET WORDCOUNT
DBRA D7,MAIN1 ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
BRA STRDONE ;QUIT IF CHARCOUNT <= 0
;
; Optimize if dst fits in one long. (30% of normal characters do)
;
LONG1 SUB #2,A3 ;ADJUST DSTEND FOR WORD BUMP
LONG1A MOVE.L (A4),D0 ;GET SRC DATA
LSR.L D5,D0 ;ALIGN TO DST
AND D3,D0 ;MASK EXTRA WITH LEFTMASK
OR D0,(A5)+ ;OR RESULT INTO DST
MOVE.L 2(A4),D0 ;GET SECOND WORD OF SRC
LSR.L D5,D0 ;ALIGN IT
AND D4,D0 ;MASK EXTRA WITH RIGHTMASK
OR D0,(A5) ;OR RESULT INTO DST
ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,LONG1A ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
BRA STRDONE ;QUIT IF CHARCOUNT <= 0
;
; Optimize if dst fits in one word. (70% of normal characters do)
;
WORD1 AND D4,D3 ;COMBINE LEFT AND RIGHT MASKS
WORD1B MOVE.L (A4),D0 ;GET SRC DATA
LSR.L D5,D0 ;ALIGN TO DST
AND D3,D0 ;MASK EXTRA TO ZEROS
OR D0,(A5) ;OR RESULT INTO DST
ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,WORD1B ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
STRDONE MOVE.L SAVEA5(A6),A5 ;RESTORE GLOBAL PTR
TST.B FASTFLAG(A6) ;WERE WE GOING DIRECT TO SCREEN ?
BEQ.S @1 ;NO, CONTINUE
JSR SHOWCURSOR ;YES, RESTORE CURSOR
BRA GOHOME ;AND QUIT
@1 MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT
MOVE.L FONTPTR(A0),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE CHARLOC(A6),D7 ;GET FINAL CHARLOC INT PART
SUB FBBOX(A2),D7 ;UN-ADJUST FROM KERNING
;
; Make buffer bold if necessary:
;
CKBOLD CLR D2 ;GET READY FOR BYTE
MOVE.B 6(A4),D2 ;GET NUMBER OF OVERSTRIKES
BRA.S NXTBOLD ;BOLD BUFFER IF ANY
BOLDIT MOVE.L BUFSTART(A6),A0 ;POINT TO START OF BUFFER
MOVE BUFSIZE(A6),D1 ;HOW MANY LONGS IN BUF
SUB D0,D0 ;CLEAR X-BIT
BOLDLP MOVE.L (A0),D0 ;GET ONE LONG
ROXR.L #1,D0 ;ROTATE RIGHT WITH EXTEND
OR.L D0,(A0)+ ;OR BACK INTO BUFFER
DBRA D1,BOLDLP ;LOOP ENTIRE BUFFER
NXTBOLD DBRA D2,BOLDIT ;LOOP FOR EACH OVERSTRIKE
;
; Slant the buffer if necessary:
; Work from bottom of buffer up, shifting each row right.
; Work right to left to avoid clobbering src.
;
CLR D2 ;GET READY FOR BYTE
MOVE.B 7(A4),D2 ;DO WE NEED ITALIC ?
BEQ.S CHECKUL ;NO, CONTINUE
MOVE.L BUFEND(A6),A1 ;DSTPTR:=END OF BUFFER
MOVE BUFROW(A6),D3 ;GET BUFFER ROWBYTES
SUB D3,A1 ;BACK UP DSTPTR TO END OF 2ND ROW
LSR #1,D3 ;WORDCNT:=ROWBYTES DIV 2
SUB #1,D3 ;WORDCOUNT-1 FOR DBRA LOOP
MOVE HEIGHT(A6),D6 ;INIT ROW COUNTER
CLR D4 ;INIT OFFSET
BRA.S DOSLANT ;GO TO LOOP START
NXTROW ADD D2,D4 ;OFFSET:=OFFSET+ITALIC
MOVE D4,D0 ;COPY OFFSET
LSR #4,D0 ;DELTA := OFFSET SCALED BY 16
MOVEQ #$F,D5
AND D0,D5 ;SHIFTCNT:=DELTA MOD 16
LSR #4,D0 ;DELWORD:=DELTA DIV 16
MOVE.L A1,A0 ;SRCPTR:=DSTPTR
SUB #4,A0 ;BACK UP ONE LONG
SUB D0,A0 ;SUBTRACT DELWORD
SUB D0,A0 ;TWICE BECAUSE WORDS
MOVE D3,D1 ;INIT LOOP TO WORDCNT
NXTWORD MOVE.L (A0),D0 ;GET A LONG OF SRC
SUB #2,A0 ;BUMP SRCPTR LEFT ONE WORD
LSR.L D5,D0 ;SHIFT SRC TO ALIGN WITH DST
MOVE D0,-(A1) ;STORE IN DST AND BUMP DSTPTR
DBRA D1,NXTWORD ;LOOP ALL WORDS THIS ROW
DOSLANT DBRA D6,NXTROW ;LOOP FOR ALL ROWS IN BUFFER
;
; Underline characters in buffer if necessary.
;
; Use characters in buffer to hide parts of the underline.
;
CHECKUL TST.B 10(A4) ;IS ULTHICK ZERO ?
BEQ NOTUL ;YES, CONTINUE
MOVE.L BUFSTART(A6),A0 ;POINT TO BUFFER START
MOVE BUFROW(A6),D1 ;GET BYTES PER ROW OF BUFFER
MOVE ASCENT(A2),D0 ;GET ASCENT
MOVE DESCENT(A2),D2 ;GET DESCENT
MULU D1,D0
ADD.L D0,A0 ;POINT TO BASELINE ROW
MOVE.L A0,A1
MOVE.L A0,A2
ADD D1,A1 ;POINT TO BASELINE+1
CMP #2,D2 ;IS DESCENT AT LEAST 2 ?
BLT.S NOTUL ;NO, SKIP UNDERLINE
BEQ.S ONLY2 ;ONLY USE 2 IF DESCENT=2
ADD D1,A2
ADD D1,A2 ;POINT TO BASELINE+2
ONLY2 SUB D1,SP ;ALLOCATE TEMP SCANBUF
MOVE.L A3,-(SP) ;SAVE GRAFPORT
LEA 4(SP),A3 ;POINT TO START OF TEMP
LSR #2,D1 ;CONVERT BYTES TO LONGS
SUB #1,D1 ;INIT DBRA LOOP COUNT
MOVE D1,D2 ;COPY LOOP COUNT
SUB D0,D0 ;CLEAR X-BIT
UL1 MOVE.L (A0)+,D0 ;GET FROM BASELINE
OR.L (A1)+,D0 ;OR WITH BASELINE+1
OR.L (A2)+,D0 ;OR WITH BASELINE+2
MOVE.L D0,(A3) ;PUT RESULT TO TEMP
ROXR.L #1,D0 ;SHIFT WITH CARRY
OR.L D0,(A3)+ ;OR INTO TEMP
DBRA D1,UL1 ;LOOP ALL LONGS IN ROW
MOVE.L A1,A0 ;COPY END PTR
SUB D0,D0 ;CLEAR X-BIT
UL2 MOVE.L -(A3),D0 ;GET FROM TEMP
ROXL.L #1,D0 ;SHIFT LEFT WITH CARRY
OR.L (A3),D0 ;OR WITH TEMP
NOT.L D0 ;INVERT
OR.L D0,-(A1) ;DRAW SOME UNDERLINE
DBRA D2,UL2 ;LOOP ALL LONGS IN ROW
MOVE.L (SP)+,A3 ;RESTORE GRAFPORT
;
; Trim right edge of underline. (left edge trimmed by StretchBits)
;
MOVE BUFROW(A6),D0 ;GET BYTES PER ROW OF BUFFER
LSL #3,D0 ;TIMES 8 FOR DOTS WIDE
SUB D7,D0 ;OVERSHOOT:=BUFRIGHT-LASTRIGHT
SUB #1,D0 ;BACK UP 1 SO MASK COMES OUT RIGHT
LSR #4,D0 ;CONVERT DOTS TO WORDCOUNT
BRA.S UL3 ;GO TO LOOP START
ULTRIM CLR -(A0) ;ERASE SOME UNDERLINE
UL3 DBRA D0,ULTRIM ;LOOP ALL FULL WORDS
ADD BUFLEFT(A6),D7 ;UNDO BUFFER RELATIVE
MOVE D7,D0 ;GET LAST RIGHT COORD
SUB PORTBOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL COORDS
JSR RIGHTMASK ;COMPUTE A MASK
AND D0,-(A0) ;ERASE LAST PARTIAL WORD
;
; Setup fakeRgn, a dummy rectangular region
;
NOTUL MOVE #10,FAKERGN+RGNSIZE(A6) ;SIZE=10 BYTES FOR RECT RGN
MOVE.L PORTBOUNDS(A3),FAKERGN+RGNBBOX(A6)
MOVE.L PORTBOUNDS+4(A3),FAKERGN+RGNBBOX+4(A6)
LEA FAKERGN(A6),A0 ;GET ADDR OF FAKERGN
MOVE.L A0,FAKEPTR(A6) ;POINT FAKE MASTERPTR TO IT
;
; Setup bitMaps to transfer from buffer to screen.
;
; srcBits := buffer
;
LEA SRCBITS(A6),A0 ;POINT TO SRCBITS
MOVE.L BUFSTART(A6),(A0)+ ;SET UP BASEADDR
MOVE BUFROW(A6),(A0)+ ;SET UP ROWBYTES
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
;
; dstBits := portBits
;
LEA PORTBITS(A3),A2 ;POINT TO PORTBITS
LEA DSTBITS(A6),A0 ;POINT TO DSTBITS
MOVE.L (A2)+,(A0)+ ;COPY BASEADDR
MOVE (A2)+,(A0)+ ;COPY ROWBYTES
MOVE.L (A2)+,(A0)+ ;COPY BOUNDS.TOPLEFT
MOVE.L (A2)+,(A0)+ ;COPY BOUNDS.BOTRIGHT
;
; check if any shadowing:
;
CLR D3 ;GET READY FOR BYTE
MOVE.B 11(A4),D3 ;GET SHADOW COUNT
BEQ NOSHAD ;SKIP IF NO SHADOWING
;
; Shadowing will be used. Allocate buf2, 4 scans taller than BUF1.
; Clear out new 4 scanlines, and copy BUF1 into the rest.
;
MOVE BUFROW(A6),D0 ;GET 4 * NUMBER OF LONGS PER ROW
SUB #1,D0 ;INIT LOOP COUNTER
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
MOVE.L SP,BUF2END(A6) ;REMEMBER END OF BUF2
CLR2 CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLR2 ;CLEAR 4 SCANLINES WORTH
MOVE BUFSIZE(A6),D0 ;GET NUMBER OF LONGS IN BUF1
SUB #1,D0 ;INIT DBRA COUNTER
MOVE.L BUFEND(A6),A0 ;POINT TO END OF BUF1
COPYLP MOVE.L -(A0),-(SP) ;COPY FROM BUF1 TO NEW BUF2
DBRA D0,COPYLP ;COPY ALL OF BUF1
MOVE.L SP,BUF2START(A6) ;REMEMBER START OF BUF2
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
;
; Bold buf2 across to the right enough for shadow.
;
AND #3,D3 ;RESTRICT SHADOW COUNT TO 1..3
MOVE D3,D2 ;INIT BOLD COUNTER
ACROSS1 MOVE.L BUF2START(A6),A0 ;POINT TO START OF BUFFER2
MOVE BUFSIZE(A6),D1 ;INIT COUNT OF LONGS
SUB D0,D0 ;CLEAR X-BIT
ACROSS2 MOVE.L (A0),D0 ;GET A LONG FROM BUF2
ROXR.L #1,D0 ;SHIFT IT RIGHT EXTENDED
OR.L D0,(A0)+ ;OR IT BACK INTO BUFFER
DBRA D1,ACROSS2 ;LOOP FOR ALL LONGS
DBRA D2,ACROSS1 ;BOLD RIGHT 2,3, OR 4 TIMES
;
; Bold BUF2 down enough for shadow.
;
MOVE.L BUF2START(A6),A2 ;GET LIMIT POINTER
DOWN1 MOVE.L BUF2END(A6),A1 ;DSTPTR:=END OF BUF2
MOVE.L A1,A0
SUB SRCBITS+ROWBYTES(A6),A0 ;SRCPTR:=END - 1 SCANLINE
DOWN2 MOVE.L -(A0),D0 ;GET A LONG FROM LINE ABOVE
OR.L D0,-(A1) ;OR INTO THIS LINE
CMP.L A2,A0 ;IS SRCPTR <= BUF2START ?
BGT DOWN2 ;NO, LOOP ALL LONGS
DBRA D3,DOWN1 ;BOLD DOWN 2,3, OR 4 TIMES
;
; Alter srcBits to use BUF2
;
MOVE.L A2,SRCBITS+BASEADDR(A6) ;SRC BASEADDR:=BUF2START
ADD #4,SRCBITS+BOUNDS+BOTTOM(A6) ;4 SCANS TALLER
;
; Push params and call StretchBits to transfer shadow to screen
;
MOVE.L TEXTRECT(A6),SRCRECT(A6) ;SRCRECT := TEXTRECT
MOVE.L TEXTRECT+4(A6),SRCRECT+4(A6)
ADD #4,SRCRECT+BOTTOM(A6) ;PLUS 4 SCANS TALLER
MOVE.L SRCRECT(A6),DSTRECT(A6) ;DSTRECT := SRCRECT
MOVE.L SRCRECT+4(A6),DSTRECT+4(A6)
LEA DSTRECT+TOP(A6),A0 ;OFFSET BY (-1,-1)
SUB #1,(A0)+ ;TOP
SUB #1,(A0)+ ;LEFT
SUB #1,(A0)+ ;BOTTOM
SUB #1,(A0)+ ;RIGHT
TST.B STRETCH(A6)
BEQ.S @1
PEA DSTRECT(A6)
PEA FROMRECT(A6)
PEA TORECT(A6)
JSR MAPRECT ;THEN MAPPED FOR SCALING
@1
PEA SRCBITS(A6) ;PUSH SRCBITS
PEA DSTBITS(A6) ;PUSH DSTBITS
PEA SRCRECT(A6) ;PUSH SRCRECT
PEA DSTRECT(A6) ;PUSH DSTRECT
MOVEQ #7,D0 ;GET A 3-BIT MASK
AND TXMODE(A3),D0 ;GET TEXTMODE MOD 7
MOVE D0,-(SP) ;PUSH SHADOW MODE
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
JSR StretchBits ;TRANSFER BUFFER TO SCREEN
;
; restore altered srcBits
;
MOVE.L BUFSTART(A6),SRCBITS+BASEADDR(A6)
SUB #4,SRCBITS+BOUNDS+BOTTOM(A6)
;
; Push params and call StretchBits to transfer buffer to screen
;
NOSHAD PEA SRCBITS(A6) ;PUSH SRCBITS
PEA DSTBITS(A6) ;PUSH DSTBITS
PEA TEXTRECT(A6) ;PUSH SRCRECT = TEXTRECT
PEA TEXTR2(A6) ;PUSH DSTRECT = TEXTR2
MOVE TXMODE(A3),-(SP) ;PUSH TEXTMODE
TST.B 11(A4) ;ARE WE USING SHADOW ?
BEQ.S MODEOK ;NO, CONTINUE
MOVE #2,(SP) ;YES, USE XOR MODE
MODEOK AND #7,(SP) ;TREAT MODE MOD 8
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
JSR StretchBits ;TRANSFER BUFFER TO SCREEN
GOHOME MOVE.L SAVESTK(A6),SP ;STRIP BUFFER
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'DRTEXT '
.END