mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-21 18:35:32 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
987 lines
34 KiB
Plaintext
987 lines
34 KiB
Plaintext
;
|
|
; File: DrawText.m.a
|
|
;
|
|
; Contains: QuickDraw Character Generator
|
|
;
|
|
; Copyright: © 1988-1990 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <3> 8/3/90 GGD Restored deleted code from last change that caused cursors to
|
|
; disappear forever.
|
|
; <2> 3/29/90 CL Getting rid of old Spline Font code. It all exists in the color
|
|
; DrawText.a code.
|
|
; <1.6> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
|
|
; file (colorequ.a), got rid of QuickDraw nFiles dependencies and
|
|
; fixed up necessary filesÉ
|
|
; <¥1.5> 5/4/89 CEL Cleaned up conditionals for ROM, HcMac works now! Blasting in
|
|
; fixÉ
|
|
; <¥1.4> 5/3/89 CEL Bass rolled into ROM. NOTE:Spline Fonts are conditionalized out.
|
|
; Blasting in correct file
|
|
; <¥1.2> 5/1/89 cel Rolled in BassÉ
|
|
; <1.1> 11/11/88 CCH Fixed Header.
|
|
; <1.0> 11/9/88 CCH Adding to EASE.
|
|
; <1.2> 10/12/88 CCH Changed Òm.GrafType.aÓ to ÒGrafType.m.aÓ.
|
|
; <1.1> 5/18/88 MSH Changed inclides to use m.GRAPHTYPES to work under EASE.
|
|
; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ
|
|
; <.3> 7/01/87 CRC Allow for fonts with strikes greater than 128K
|
|
; <.2> 11/12/87 DAF Added toolequ.a to build for somebody's incorrectly
|
|
; rolled-in patches.
|
|
; <.1> 4/29/85 BA Completely reworked to get 50% speed up. Takes advantage of
|
|
; optional height table at end of font.
|
|
;
|
|
;
|
|
; To Do:
|
|
;
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
|
|
|
|
INCLUDE 'toolequ.a' ;<C964/12Nov87> DAF
|
|
INCLUDE 'GRAFTYPES.m.a'
|
|
|
|
DrText PROC EXPORT
|
|
IMPORT TrimRect, RSect, MaskTab, RightMask, StretchBits
|
|
IMPORT ShieldCursor, ShowCursor, MapRect
|
|
;------------------------------------------------------------
|
|
;
|
|
; 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
|
|
BUFSIZE EQU BUFEND-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
|
|
FASTFLAG EQU FAKEPTR-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
|
|
BUFSTART EQU DENOM2-4 ;LONG \ start of bits buffer
|
|
SRCADDR EQU BUFSTART-4 ;LONG >- these 3 grouped: address of font bits
|
|
SRCROW EQU SRCADDR-4 ;LONG / rowbytes of font bits
|
|
VARSIZE EQU SRCROW ;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
|
|
MOVE.L JStdTxMeas,A0 ;get piece of trap table
|
|
JSR (A0) ;MEASURE TEXT
|
|
MOVE (SP)+,D1 ;POP UNSCALED WIDTH RESULT
|
|
;
|
|
; StdTxMeas also stashes FMOutPtr in QD global FONTPTR,
|
|
; and unscaled fixed point text width in 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
|
|
EXT.L D1 ;Make it a long <1.4-4april89-CEL>
|
|
MOVE.L D1,SRCROW(A6) ;REMEMBER FOR LATER <1.4-4april89-CEL>
|
|
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.B fmOutItalic(A4) ;TEST BOLD $$$
|
|
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
|
|
@skipItalic
|
|
TST.B fmOutBold(A4) ;TEST BOLD
|
|
BNE NOTFAST ;NOT FAST
|
|
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 ?
|
|
BMI.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
|
|
MULS 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 ; <3>
|
|
|
|
;
|
|
; 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.S @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(A6),PNLOC(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
|
|
EXT.L D0 ;Make it a long to clear top half <1.4-4april89-CEL>
|
|
MOVE.L SRCROW(A6),D1 ;CALC TOTAL SIZE OF STRIKE <1.4-4april89-CEL>
|
|
MULU D1,D0 ;CALC TOTAL SIZE OF STRIKE <1.4-4april89-CEL>
|
|
ADD.L D0,A0 ;A1 := START OF LOC TABLE
|
|
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
|
|
|
|
MOVE.W fNDescent(A2),D0 ;possibly the high word of owTLoc
|
|
SWAP D0 ;put it in the high word
|
|
BPL.S @notNegative
|
|
MOVEQ #0,D0 ;old fonts have negative of ascent here
|
|
@notNegative
|
|
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 WidthTabHandle, A0 ;Get the Width Table <1.4-4april89-CEL>
|
|
MOVE.L (A0), A0 ;Dereference the table <1.4-4april89-CEL>
|
|
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:
|
|
;
|
|
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 NOTMISS ;IS MISSING CHAR MISSING ?
|
|
BRA.S NEXTCH ;YES, SKIP THIS CHAR
|
|
|
|
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.S SPACECH ;YES, HANDLE IT
|
|
|
|
MOVE.L WidthTabHandle, A0 ;Get the Width Table
|
|
MOVE.L (A0), A0 ;Dereference the 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 ?
|
|
BHI MISSING ;Missing so miss it <1.4-4april89-CEL>
|
|
|
|
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
|
|
MOVE BUFROW(A6),A3 ;Get Bufrow in A3 <1.4-4april89-CEL>
|
|
MOVEM.L SRCROW(A6),A2/A4-A5 ;srcRow, srcAddr (src bitmap), bufStart (dst bitmap) <1.4-4april89-CEL>
|
|
|
|
;
|
|
; Setup srcAddr in A4, address of leftmost word
|
|
;
|
|
; MOVE.L SRCADDR(A6),A4 ;GET START OF SRC BITMAP <1.4-4april89-CEL>
|
|
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 <1.4-4april89-CEL>
|
|
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.L SRCROW(A6),A2 ;It is a long now <1.4-4april89-CEL>
|
|
; MOVE SRCROW(A6),A2 <1.4-4april89-CEL>
|
|
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.L A2,D2 ;get srcRow in D-reg <1.4-4april89-CEL>
|
|
; MOVE A2,D2 ;get srcRow in D-reg <1.4-4april89-CEL>
|
|
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.L A2,A4 ;BUMP TO NEXT ROW <1.4-4april89-CEL>
|
|
; ADD A2,A4 ;BUMP TO NEXT ROW <1.4-4april89-CEL>
|
|
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.S 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.L A2,A4 ;BUMP SRCPTR TO NEXT ROW <1.4-4april89-CEL>
|
|
; ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW <1.4-4april89-CEL>
|
|
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.S 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.L A2,A4 ;BUMP SRCPTR TO NEXT ROW <1.4-4april89-CEL>
|
|
; ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW <1.4-4april89-CEL>
|
|
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.S 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
|
|
|
|
|