QuickDraw/Text.a

741 lines
32 KiB
Plaintext
Executable File

.INCLUDE GRAFTYPES.TEXT
;---------------------------------------------------------
;
;
; ***** ***** * * *****
; * * * * *
; * * * * *
; * *** * *
; * * * * *
; * * * * *
; * ***** * * *
;
;
; Routines for measuring and drawing Text.
;
;-------------------------------------------
;
; 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
.PROC StdText,4
.REF CheckPic,DPutPicByte,PutPicData,PutPicWord,PutPicLong
.REF DrText
;--------------------------------------------------------------------------
;
; PROCEDURE StdText(count: INTEGER; textAddr: Ptr; numer,denom: Point);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 14
COUNT .EQU PARAMSIZE+8-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG
NUMER .EQU TEXTADDR-4 ;POINT
DENOM .EQU NUMER-4 ;POINT
TXLOC .EQU -4 ;POINT
VARSIZE .EQU TXLOC ;TOTAL LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D5-D7/A3-A4,-(SP) ;SAVE REGS
TXTLOOP MOVE COUNT(A6),D6 ;GET CHARACTER COUNT
BLE GOHOME ;QUIT IF COUNT <= 0
CMP #255,D6 ;is count > 255 ?
BLE.S COUNTOK ;no, continue
MOVE #255,D6 ;yes, pin at 255
COUNTOK JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE NOTPIC
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
;
; CHECK TXFONT
;
MOVE TXFONT(A3),D7 ;GET THEPORT^.TXFONT
CMP PICTXFONT(A4),D7 ;HAS IT CHANGED ?
BEQ.S FONTOK ;NO, CONTINUE
MOVEQ #3,D0 ;YES, PUSH TXFONT PARAM OPCODE
JSR DPutPicByte ;PUT OPCODE
MOVE D7,-(SP)
JSR PutPicWord ;PUT TXFONT PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE D7,PICTXFONT(A4) ;UPDATE CURRENT STATE
;
; CHECK TXFACE
;
FONTOK MOVE.B TXFACE(A3),D7 ;GET THEPORT^.TXFACE
CMP.B PICTXFACE(A4),D7 ;HAS IT CHANGED ?
BEQ.S FACEOK ;NO, CONTINUE
MOVEQ #4,D0 ;YES, PUSH TXFACE PARAM OPCODE
JSR DPutPicByte ;PUT OPCODE
MOVE.B D7,D0
JSR DPutPicByte ;PUT TXFACE PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.B D7,PICTXFACE(A4) ;UPDATE CURRENT STATE
;
; CHECK TXMODE
;
FACEOK MOVE TXMODE(A3),D7 ;GET THEPORT^.TXMODE
CMP PICTXMODE(A4),D7 ;HAS IT CHANGED ?
BEQ.S MODEOK ;NO, CONTINUE
MOVEQ #5,D0 ;YES, PUSH TXMODE PARAM OPCODE
JSR DPutPicByte ;PUT OPCODE
MOVE D7,-(SP)
JSR PutPicWord ;PUT TXMODE PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE D7,PICTXMODE(A4) ;UPDATE CURRENT STATE
;
; CHECK TXSIZE
;
MODEOK MOVE TXSIZE(A3),D7 ;GET THEPORT^.TXSIZE
CMP PICTXSIZE(A4),D7 ;HAS IT CHANGED ?
BEQ.S SIZEOK ;NO, CONTINUE
MOVEQ #$0D,D0 ;YES, PUSH TXSIZE PARAM OPCODE
BSR.S JDPutPicByte ;PUT OPCODE
MOVE D7,-(SP)
JSR PutPicWord ;PUT TXSIZE PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE D7,PICTXSIZE(A4) ;UPDATE CURRENT STATE
;
; CHECK SPEXTRA
;
SIZEOK MOVE.L SPEXTRA(A3),D7 ;GET THEPORT^.SPEXTRA
CMP.L PICSPEXTRA(A4),D7 ;HAS IT CHANGED ?
BEQ.S SPOK ;NO, CONTINUE
MOVEQ #6,D0 ;YES, PUSH SPEXTRA PARAM OPCODE
BSR.S JDPutPicByte ;PUT OPCODE
MOVE.L D7,-(SP)
BSR.S JPutPicLong ;PUT SPEXTRA PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L D7,PICSPEXTRA(A4) ;UPDATE CURRENT STATE
;
; CHECK NUMER, DENOM
;
SPOK MOVE.L NUMER(A6),D7 ;GET NUMER
MOVE.L DENOM(A6),D5 ;GET DENOM
CMP.L PICTXNUMER(A4),D7 ;HAS IT CHANGED ?
BNE.S NOTSAME ;YES, RECORD CHANGE
CMP.L PICTXDENOM(A4),D5 ;HAS IT CHANGED ?
BEQ.S NUMEROK ;NO, CONTINUE
NOTSAME MOVEQ #$10,D0 ;YES, PUSH TXRATIO OPCODE
BSR.S JDPutPicByte ;PUT OPCODE
MOVE.L D7,-(SP)
BSR.S JPutPicLong ;PUT NUMER
MOVE.L D5,-(SP)
BSR.S JPutPicLong ;PUT DENOM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L D7,PICTXNUMER(A4) ;UPDATE CURRENT STATE
MOVE.L D5,PICTXDENOM(A4) ;UPDATE CURRENT STATE
NUMEROK
;-------------------------------------------------------------
;
; USE DH AND DV TO CHOOSE ONE OF FOUR TEXT OPCODES.
;
MOVE.L PNLOC(A3),D5 ;GET CURRENT PNLOC
SUB.L PICTXLOC(A4),D5 ;CALC DV.DH
MOVE.L D5,D0 ;COPY DV.DH
AND.L #$FF00FF00,D0 ;ARE DH AND DV BOTH 0..255 ?
BEQ.S SHORT ;YES, USE SHORT FORM
MOVEQ #$28,D0
BSR.S JDPutPicByte ;NO, PUT LONGTEXT OPCODE
MOVE.L PNLOC(A3),-(SP)
BSR.S JPutPicLong ;PUT PNLOC 4 BYTES
BRA.S TEXT2 ;AND CONTINUE
JDPutPicByte
JMP DPutPicByte
JPutPicLong
JMP PutPicLong
SHORT MOVE.L D5,D0 ;YES, COPY DV.DH
AND.L #$00FF0000,D0 ;IS DV = 0 ?
BNE.S DV ;NO, CONTINUE
MOVEQ #$29,D0
BSR.S JDPutPicByte ;YES, PUT DHTEXT OPCODE
BRA.S SHARE2 ;SHARE COMMON CODE
DV TST.B D5 ;IS DH = 0 ?
BNE.S DHDV ;NO, CONTINUE
MOVEQ #$2A,D0
BSR.S JDPutPicByte ;YES, PUT DVTEXT OPCODE
BRA.S SHARE1 ;SHARE COMMON CODE
DHDV MOVEQ #$2B,D0
BSR.S JDPutPicByte ;PUT DHDVTEXT OPCODE
MOVE.B D5,D0
BSR.S JDPutPicByte ;PUT DH 0..255 TO PIC
SHARE1 SWAP D5 ;PUT DV IN LO WORD
SHARE2 MOVE.B D5,D0
BSR.S JDPutPicByte ;PUT DH OR DV 0..255 TO PIC
TEXT2 MOVE.B D6,D0
BSR.S JDPutPicByte ;PUT COUNT BYTE TO PIC
MOVE.L TEXTADDR(A6),-(SP) ;PUSH ADDR OF TEXT
MOVE D6,-(SP) ;PUSH COUNT
JSR PutPicData ;PUT TEXT DATA
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L PNLOC(A3),PICTXLOC(A4) ;UPDATE PICTXLOC STATE
;
; DrText(count,textAddr,numer,denom);
;
NOTPIC MOVE D6,-(SP) ;PUSH COUNT
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
MOVE.L NUMER(A6),-(SP) ;PUSH NUMER
MOVE.L DENOM(A6),-(SP) ;PUSH DENOM
JSR DrText ;DRAW THE TEXT
SUB D6,COUNT(A6) ;was count > 255 ?
BLE.S GOHOME ;no, quit
MOVE.L TEXTADDR(A6),A0 ;yes, get old textaddr
ADD D6,A0 ;offset for characters done
MOVE.L A0,TEXTADDR(A6) ;update textAddr
BRA TXTLOOP ;and loop for more
GOHOME MOVEM.L (SP)+,D5-D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDTEXT '
.PROC CallText,2
.REF STDTEXT
;---------------------------------------------------------------
;
; PROCEDURE CallText(count: INTEGER; textAddr: Ptr);
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L #$00010001,-(SP) ;PUSH NUMER = (1,1)
MOVE.L (SP),-(SP) ;PUSH DENOM = (1,1)
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDTEXT,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L TEXTPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.PROC TextFace,1
.DEF DrawChar,CharWidth
.REF CallText,TextWidth
;-------------------------------------------------------
;
; PROCEDURE TextFace(face: Style);
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.B 5(SP),TXFACE(A0) ;INSTALL TXFACE
BRA.S SHARE ;STRIP PARAM AND RETURN
;----------------------------------------------------
;
; PROCEDURE DrawChar(ch: CHAR);
;
DrawChar
MOVE #1,-(SP) ;PUSH COUNT=1
PEA 7(SP) ;PUSH TEXTADDR
JSR CallText ;CALL TEXT ROUTINE
BRA.S SHARE ;STRIP PARAM AND RETURN
;---------------------------------------------
;
; FUNCTION CharWidth(ch: CHAR): INTEGER;
;
CharWidth
CLR -(SP) ;ROOM FOR FCN RESULT
MOVE.L SP,-(SP) ;PUSH TEXTBUF
MOVE.L #$00010007,-(SP) ;PUSH OFFSET = 7 & COUNT = 1
JSR TEXTWIDTH
MOVE (SP)+,6(SP) ;MOVE UP RESULT
SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD #2,SP ;STRIP CHAR PARAM
JMP (A0) ;AND RETURN
.PROC TextFont,1
.DEF TextSize
.DEF TextMode
.REF PortWord
;-------------------------------------------------------
;
; PROCEDURE TextFont(font: INTEGER);
;
MOVEQ #TXFONT,D0 ;PUT PORT OFFSET IN D0
BRA.S SHARE
;-------------------------------------------------------
;
; PROCEDURE TextMode(mode: INTEGER);
;
TextMode
MOVEQ #TXMODE,D0 ;PUT PORT OFFSET IN D0
BRA.S SHARE
;-------------------------------------------------------
;
; PROCEDURE TextSize(mode: INTEGER);
;
TextSize
MOVEQ #TXSIZE,D0 ;PUT PORT OFFSET IN D0
SHARE JMP PORTWORD ;INSTALL PARAM INTO THEPORT
.PROC SpaceExtra,1
.DEF DrawString,DrawText
.REF CallText
;-------------------------------------------------------
;
; PROCEDURE SpaceExtra(extra: LongInt);
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.L 4(SP),SPEXTRA(A0) ;INSTALL FIXED POINT SPEXTRA
BRA.S SHARE
;----------------------------------------------------
;
; PROCEDURE DrawString(s: Str255);
;
DrawString
MOVE.L 4(SP),A0 ;POINT TO STRING
CLR D0 ;GET READY FOR BYTE
MOVE.B (A0)+,D0 ;GET STRING LENGTH
MOVE D0,-(SP) ;PUSH COUNT
MOVE.L A0,-(SP) ;PUSH TEXTADDR
JSR CallText ;CALL TEXT ROUTINE
BRA.S SHARE
;----------------------------------------------------
;
; PROCEDURE DrawText(textBuf: WordPtr; start,count: INTEGER);
;
DrawText
MOVE.L 8(SP),A0 ;POINT TO TEXTBUF
ADD 6(SP),A0 ;ADD STARTING OFFSET
MOVE 4(SP),-(SP) ;PUSH COUNT
MOVE.L A0,-(SP) ;PUSH TEXTADDR
JSR CallText ;CALL TEXT ROUTINE
MOVE.L (SP)+,(SP)
SHARE MOVE.L (SP)+,(SP) ;STRIP PARAMS
RTS ;AND RETURN
.FUNC StringWidth,1
.REF TextWidth
;---------------------------------------------
;
; FUNCTION StringWidth(s: Str255): INTEGER;
;
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE.L (SP)+,A0 ;POP ADDR OF STRING
CLR D0
MOVE.B (A0)+,D0 ;GET UNSIGNED BYTE
MOVE.L A0,-(SP) ;PUSH TEXTADDR
CLR -(SP) ;FIRSTBYTE := 0
MOVE D0,-(SP) ;PUSH BYTECOUNT
MOVE.L A1,-(SP) ;PUT BACK RETURN ADDR
;
; FALL THRU INTO TEXTWIDTH
;
.FUNC TextWidth,3
.REF StdTxMeas
;------------------------------------------
;
; FUNCTION TEXTWIDTH(TEXTBUF: WordPtr; firstbyte,byteCount: INTEGER): INTEGER;
;
PARAMSIZE .EQU 8
RESULT .EQU PARAMSIZE+8
TEXTBUF .EQU RESULT-4 ;LONG
FIRSTBYTE .EQU TEXTBUF-2 ;WORD
BYTECOUNT .EQU FIRSTBYTE-2 ;WORD
INFO .EQU -8 ;4 WORDS
NUMER .EQU INFO-4 ;POINT
DENOM .EQU NUMER-4 ;POINT
VARSIZE .EQU DENOM ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
CLR RESULT(A6) ;INIT RESULT TO 0
CLR -(SP) ;MAKE ROOM FOR FCN CALL BELOW
MOVE BYTECOUNT(A6),-(SP) ;PUSH BYTE COUNT
BLE.S GOHOME ;QUIT IF COUNT <= 0
;UNLK TAKES CARE OF SP
MOVE.L TEXTBUF(A6),A0 ;GET ADDR OF BUFFER
ADD FIRSTBYTE(A6),A0 ;ADD STARTING INDEX
MOVE.L A0,-(SP) ;PUSH TEXTADDR
MOVE.L #$00010001,D0
MOVE.L D0,NUMER(A6) ;NUMER := (1,1)
MOVE.L D0,DENOM(A6) ;DENOM := (1,1)
PEA NUMER(A6) ;PUSH VAR NUMER
PEA DENOM(A6) ;PUSH VAR DENOM
PEA INFO(A6) ;PUSH VAR INFO
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
BEQ.S STD ;YES, USE STDTXMEAS
MOVE.L D0,A0 ;NO, GET GRAFPROCS
MOVE.L TXMEASPROC(A0),A0 ;GET TXMEAS CAPTURE PROC
JSR (A0) ;CALL IT
BRA.S NOTSTD ;AND CONTINUE
STD JSR STDTXMEAS
NOTSTD MOVE (SP)+,D1 ;POP UNSCALED WIDTH
MOVE NUMER+H(A6),D0 ;get numer
MOVE DENOM+H(A6),D2 ;get denom
CMP D2,D0 ;is numer same as denom ?
BEQ.S DONE ;yes, skip muldiv
MULU D0,D1 ;MUL BY NUMER
MOVE D2,D0 ;COPY DENOM
LSR #1,D0 ;CALC DENOM DIV 2
ADD D0,D1 ;ADD DENOM DIV 2
DIVU D2,D1 ;DIV BY DENOM
DONE MOVE D1,RESULT(A6) ;RETURN SCALED WIDTH
GOHOME UNLINK PARAMSIZE,'TEXTWIDT'
.FUNC StdTxMeas,5
;------------------------------------------
;
; FUNCTION StdTxMeas(count: INTEGER; textAddr: Ptr;
; VAR numer,denom: Point;
; VAR info: FontInfo): INTEGER;
;
; Measure some text, returning unscaled values plus updated scale factor.
; Fills info record with unscaled ascent, descent, widMax, and leading,
; and returns unscaled integer width as the function value.
;
; Also leaves unscaled fixed point width in QD global 'fixTxWid'
; and stashes FMOutPtr in QD global 'fontPtr' for DrawText.
;
PARAMSIZE .EQU 18
RESULT .EQU PARAMSIZE+8 ;FCN RESULT IS A WORD
COUNT .EQU RESULT-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG
NUMER .EQU TEXTADDR-4 ;LONG, VAR ADDR
DENOM .EQU NUMER-4 ;LONG, VAR ADDR
INFO .EQU DENOM-4 ;LONG, ADDR OF FONTINFO
INREC .EQU -16 ;FMInput record
VARSIZE .EQU INREC
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVE.L A4,-(SP) ;SAVE REG
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A0 ;GET CURRENT GRAFPORT
LEA INREC(A6),A1 ;POINT TO FMINPUT RECORD
MOVE TXFONT(A0),(A1)+ ;GET TXFONT FROM THEPORT
MOVE TXSIZE(A0),(A1)+ ;GET TXSIZE FROM THEPORT
MOVE.B TXFACE(A0),(A1)+ ;GET TXFACE FROM THEPORT
ST (A1)+ ;ALWAYS SET NEEDBITS TRUE
MOVE DEVICE(A0),(A1)+ ;GET DEVICE FROM THEPORT
MOVE.L NUMER(A6),A0 ;POINT TO NUMER
MOVE.L (A0),(A1)+ ;INSTALL INPUT NUMER
MOVE.L DENOM(A6),A0 ;POINT TO DENOM
MOVE.L (A0),(A1)+ ;INSTALL INPUT DENOM
CLR.L -(SP) ;ROOM FOR FCN RESULT
PEA INREC(A6) ;PUSH INPUT RECORD
_SwapFont ;CALL FMSWAPFONT
MOVE.L (SP)+,A1 ;POP FMOUTPUT POINTER
MOVE.L A1,FONTPTR(A4) ;STASH FMOUTPTR FOR LATER
MOVE.L INFO(A6),A0 ;POINT TO VAR INFO RECORD
CLR.L (A0) ;INIT TO (0,0,0,0)
CLR.L 4(A0) ;ALL 4 WORDS
MOVE.B 13(A1),1(A0) ;FILL IN UNSIGNED ASCENT
MOVE.B 14(A1),3(A0) ;FILL IN UNSIGNED DESCENT
MOVE.B 15(A1),5(A0) ;FILL IN UNSIGNED WIDMAX
MOVE.B 16(A1),D0 ;GET SIGNED LEADING
EXT.W D0 ;SIGN EXTEND TO WORD
MOVE.W D0,6(A0) ;FILL IN LEADING
;
; UPDATE NUMER AND DENOM
;
MOVE.L NUMER(A6),A0 ;GET VAR ADDR
MOVE.L 18(A1),(A0) ;UPDATE NUMER
MOVE.L DENOM(A6),A0 ;GET VAR ADDR
MOVE.L 22(A1),(A0) ;UPDATE DENOM
MOVE.L TEXTADDR(A6),A0 ;POINT TO CHARACTERS
MOVE.L WidthPtr,A1 ;POINT TO WIDTH TABLE
CLR.L D1 ;INIT WIDTH TO 0.0
MOVE COUNT(A6),D2 ;GET CHARACTER COUNT
BRA.S MORE ;GO TO LOOP START
NEXTCH CLR D0 ;GET READY FOR BYTE
MOVE.B (A0)+,D0 ;GET A CHARACTER
LSL #2,D0 ;QUAD FOR TABLE OFFSET
ADD.L 0(A1,D0),D1 ;ADD FIXED POINT WIDTH
MORE DBRA D2,NEXTCH ;LOOP FOR ALL CHARS
MOVE.L D1,fixTxWid(A4) ;STASH FIXED POINT WIDTH
SWAP D1 ;GET HI WORD = INTEGER PORTION
MOVE D1,RESULT(A6) ;UPDATE FUNCTION RESULT
MOVE.L (SP)+,A4 ;RESTORE REG
UNLINK PARAMSIZE,'STDTXMEA'
.PROC MeasureText
;--------------------------------------------------------------------
;
; PROCEDURE MeasureText(count: INTEGER; textAddr,charLocs: Ptr);
;
; Measure some text, returning (scaled) screen widths in charlocs.
;
; Charlocs points to an array of count+1 integers.
;
PARAMSIZE .EQU 10
COUNT .EQU PARAMSIZE+8-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG, Ptr to ASCII
CHARLOCS .EQU TEXTADDR-4 ;LONG, Ptr to output array
INREC .EQU -16 ;FMInput record
VARSIZE .EQU INREC
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVEM.L D3-D4/A2,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
;
; Call swapfont to set up width table and return numer,denom:
;
LEA INREC(A6),A1 ;POINT TO FMINPUT RECORD
MOVE TXFONT(A0),(A1)+ ;GET TXFONT FROM THEPORT
MOVE TXSIZE(A0),(A1)+ ;GET TXSIZE FROM THEPORT
MOVE.B TXFACE(A0),(A1)+ ;GET TXFACE FROM THEPORT
ST (A1)+ ;ALWAYS SET NEEDBITS TRUE
MOVE DEVICE(A0),(A1)+ ;GET DEVICE FROM THEPORT
MOVE.L #$00010001,(A1)+ ;INSTALL INPUT NUMER = 1,1
MOVE.L #$00010001,(A1)+ ;INSTALL INPUT DENOM = 1,1
CLR.L -(SP) ;ROOM FOR FCN RESULT
PEA INREC(A6) ;PUSH INPUT RECORD
_SwapFont ;CALL FMSWAPFONT
MOVE.L (SP)+,A0 ;POP FMOUTPUT POINTER
MOVE.W 18+H(A0),D3 ;GET NUMER.H
MOVE.W 22+H(A0),D4 ;GET DENOM.H
;
; Step thru characters, adding up unscaled widths and storing in charLocs:
;
MOVE.L TEXTADDR(A6),A0 ;POINT TO CHARACTERS
MOVE.L WidthPtr,A1 ;POINT TO WIDTH TABLE
MOVE.L CHARLOCS(A6),A2 ;POINT TO CHARLOCS
CLR.L D1 ;INIT WIDTH TO 0.0
MOVE COUNT(A6),D2 ;GET CHARACTER COUNT
NEXTCH SWAP D1 ;GET HI WORD OF WIDTH
MOVE.W D1,(A2)+ ;STORE IN CHARLOCS
SWAP D1 ;RETURN WIDTH TO FIXED POINT
CLR D0 ;GET READY FOR BYTE
MOVE.B (A0)+,D0 ;GET A CHARACTER
LSL #2,D0 ;QUAD FOR TABLE OFFSET
ADD.L 0(A1,D0),D1 ;ADD FIXED POINT WIDTH
MORE DBRA D2,NEXTCH ;LOOP FOR COUNT+1 CHARLOCS
;
; if font is horizontally stretched, scale all widths accordingly
;
CMP D3,D4 ;IS NUMER.H = DENOM.H ?
BEQ.S NOSCALE ;YES, SKIP SCALING
MOVE D4,D1 ;COPY DENOM
LSR #1,D1 ;CALC DENOM DIV 2
MOVE.L CHARLOCS(A6),A2 ;NO, POINT TO CHARLOCS
MOVE COUNT(A6),D2 ;GET CHARACTER COUNT
NEXTCH2 MOVE (A2),D0 ;GET CHARLOC
MULU D3,D0 ;MUL BY NUMER
ADD D1,D0 ;ADD DENOM DIV 2
DIVU D4,D0 ;DIV BY DENOM
MOVE D0,(A2)+ ;UPDATE CHARLOC
DBRA D2,NEXTCH2 ;LOOP FOR COUNT+1 CHARLOCS
NOSCALE
MOVEM.L(SP)+,D3-D4/A2 ;RESTORE REGS
UNLINK PARAMSIZE,'MEASURET'
;--------------------------------------------------------------------
;
; FUNCTION FMSwapFont(inRec: FMInput): FMOutPtr;
;
; FMSwapFont is the only contact between QuickDraw and the Font Manager.
; It swaps in the requested font and returns a pointer to an output record
; telling how to use the font. FMSwapFont is called from StdTxMeas
; in response to DrawChar, DrawString, DrawText, CharWidth, StringWidth,
; TextWidth, and GetFontInfo.
;
; IF fontHandle returns as Nil (can't find the font), then:
; 1. The output record will be undefined except for errNum and fontHandle.
; 2. DrawString will neither draw the text nor bump the pen.
; 3. StringWidth will return 0.
; 4. GetFontInfo will return 0,0,0,0.
;
;
; FMInput = PACKED RECORD
; family: INTEGER; { i.e. Century }
; size: INTEGER; { i.e. 12 point }
; face: Style; { i.e. [bold,underlined] }
; needBits: BOOLEAN; { do we need the bitmaps ? }
; device: INTEGER; { i.e. 0 for screen }
; numer: Point; { current drawing scale }
; denom: Point; { current drawing scale }
; END;
;
;
; FMOutPtr = ^FMOutPut;
; FMOutput = PACKED RECORD
; errNum: INTEGER; { not used }
; fontHandle: Handle; { handle to font }
; bold: Byte; { how much to smear horiz }
; italic: Byte; { how much to shear }
; ulOffset: Byte; { pixels below baseline }
; ulShadow: Byte; { how big is the halo }
; ulThick: Byte; { how thick is the underline }
; shadow: Byte; { 0,1,2,or 3 only }
; extra: SignedByte; { extra white dots each char }
; ascent: Byte; { ascent measure for font }
; descent: Byte; { descent measure for font }
; widMax: Byte; { width of widest char }
; leading: SignedByte; { leading between lines }
; unused: Byte;
; numer: Point; { use this modified scale to }
; denom: Point; { draw or measure text with }
; END;
;
;
;
;--------------------------------------------------------------------------
.PROC GetFontInfo,1
.REF StdTxMeas
;------------------------------------------
;
; PROCEDURE GetFontInfo(VAR info: FontInfo);
;
; Calls StdTxMeas thru capture proc, then adjusts and scales the result.
;
; 13 MAY 85, changed so that all 4 values round UP in the case of scaling.
;
PARAMSIZE .EQU 4
INFO .EQU PARAMSIZE+8-4 ;LONG, ADDR OF INFO
NUMER .EQU -4 ;POINT
DENOM .EQU NUMER-4 ;POINT
VARSIZE .EQU DENOM ;TOTAL LOCALS
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVE.L #$00010001,NUMER(A6) ;NUMER := (1,1)
MOVE.L #$00010001,DENOM(A6) ;DENOM := (1,1)
CLR.L -(SP) ;ROOM FOR FCN, COUNT = 0
CLR.L -(SP) ;TEXTADDR := NIL
PEA NUMER(A6) ;PUSH VAR NUMER
PEA DENOM(A6) ;PUSH VAR DENOM
MOVE.L INFO(A6),-(SP) ;PUSH VAR INFO
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDTXMEAS,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L TXMEASPROC(A0),A0 ;NO, GET TXMEAS CAPTURE PROC
USESTD JSR (A0) ;CALL IT
TST (SP)+ ;DISCARD WIDTH FCN RSLT
;
; ADJUST WIDMAX FOR EXTRA
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L FONTPTR(A0),A0 ;GET FMOUTPUT RECORD
MOVE.L INFO(A6),A1 ;POINT TO RESULT INFO
MOVE.B 12(A0),D0 ;GET SIGNED EXTRA
EXT.W D0 ;EXTEND TO WORD
ADD D0,4(A1) ;ADD TO WIDMAX
;
; ADJUST ASCENT & DESCENT FOR SHADOW
;
CLR D0 ;GET READY FOR BYTE
MOVE.B 11(A0),D0 ;GET SHADOW COUNT
BEQ.S NOTSHAD ;SKIP IF ZERO
ADD #1,0(A1) ;ADJUST ASCENT
ADD D0,2(A1) ;ADJUST DESCENT
NOTSHAD
;
; SCALE RESULT IF NUMER <> DENOM
;
MOVE.L NUMER(A6),D0
CMP.L DENOM(A6),D0 ;IS NUMER SAME AS DENOM ?
BEQ.S NOSCALE ;YES, SKIP SCALING
BSR.S SCALE ;SCALE ASCENT
BSR.S SCALE ;SCALE DESCENT
MOVE (A1),D0 ;GET MAXWID
MULU NUMER+H(A6),D0 ;SCALE MAXWID
MOVE DENOM+H(A6),D1 ;get denom
SUB #1,D1 ;calc denom-1
EXT.L D1 ;extend to long
ADD.L D1,D0 ;add denom-1 to round up
DIVU DENOM+H(A6),D0 ;divide by denom
MOVE D0,(A1)+ ;UPDATE MAXWID
BSR.S SCALE ;SCALE LEADING
NOSCALE UNLINK PARAMSIZE,'GETFONTI'
SCALE MOVE (A1),D0 ;GET IT
MULU NUMER+V(A6),D0 ;SCALE IT
MOVE DENOM+V(A6),D1 ;get denom
SUB #1,D1 ;calc denom-1
EXT.L D1 ;extend to long
ADD.L D1,D0 ;add denom-1 to round up
DIVU DENOM+V(A6),D0 ;divide by denom
MOVE D0,(A1)+ ;UPDATE IT
RTS
.END