mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 01:49:19 +00:00
2923 lines
109 KiB
Plaintext
2923 lines
109 KiB
Plaintext
;EASE$$$ READ ONLY COPY of file “FontMgrPatch.a”
|
||
; 1.3 CCH 04/17/1989 Unconditionalized fixes from 6.0.3.
|
||
; 1.2 CCH 01/31/1989 Merged changes from 6.0.3.
|
||
; 1.1 CCH 01/16/1989 Merged 6.0.3 final sources into 7.0.
|
||
; 1.0 CCH 11/16/1988 Added to EASE.
|
||
; END EASE MODIFICATION HISTORY
|
||
; File: FontMgrPatch.a
|
||
;
|
||
;________________________________________________________________________________
|
||
; NOTICE: When entering patches use the format that is described below...
|
||
;
|
||
; Please read the following description for
|
||
; the Patch Collator. Patch Collator will
|
||
; aid us in finding out where system
|
||
; patches are located. Therefore, making
|
||
; it a little easier to track down rodents!
|
||
;
|
||
;
|
||
; Patch Collator for the Macintosh System Disk
|
||
; ============================================
|
||
;
|
||
; File: patch.c
|
||
; Language: "C"
|
||
;
|
||
; Date: April 16, 1987
|
||
; Revision: 1.0
|
||
; Author: Charlton E. Lui
|
||
;
|
||
; Patch collator is a simple program that scans through files looking for Apple System Patches.
|
||
; It finds a patch comment by finding a header that looks like this...
|
||
;
|
||
; *** One to one mapping of a fix ***
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;*AppleSystemPatch FontMgrPatch.a 08Jul85 #0 (InstallRDrivers) (InstallRDrivers)
|
||
;
|
||
; *** One to many mapping of a fix ***
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;*AppleSystemPatch FontMgrPatch.a 09Dec85 #13 (SoundVBLAddress) (RecoverHandle,ROMBMap)
|
||
;
|
||
; *** Many to one mapping of a fix ***
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;*AppleSystemPatch FontMgrPatch.a 17May86 #47 (FontMgr,DialogMgr) (GetRsrc)
|
||
;
|
||
; *** One to many mapping of a fix ***
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;*AppleSystemPatch FontMgrPatch.a 23Apr86 #43 (BTFlush,BTClose) (BTFlush,BTClose)
|
||
;
|
||
;
|
||
;
|
||
; The examples show the many mappings a fix may have. Each file should have the appropiate ROM
|
||
; version already inserted atop the file so it does not need be entered.
|
||
;
|
||
; WARNING: To make sure the scan works properly, use parenthesis around the routine field(s).
|
||
;
|
||
; This header will be inserted atop of each patch file. Whenever a new patch is entered the person
|
||
; who is entering the patch will copy the header down to the place where they are making the fix
|
||
; and enter the pertinent information.
|
||
;
|
||
; IMPORTANT! Make sure to take out the asterix before the AppleSystemPatch symbol.
|
||
; The "*" was added so that Patch Collator would not mistake the comments above as
|
||
; an actual patch. So delete the "*" before. Also, make sure that there is no
|
||
; space between the ";"(semicolon) and the "AppleSystemPatch" symbol. It should look like this
|
||
; ";AppleSystemPatch".
|
||
;
|
||
; A file will contain a list of names of the main patch files. Patch collator will use
|
||
; MPW's funnel facility to feed the names into the patch collator.
|
||
;
|
||
; PatchCollator < PatchFiles
|
||
;
|
||
; The files will also be scanned for other patch file includes. The included patch files will
|
||
; be added to the list of patch files.
|
||
;
|
||
; Each file will be scanned for patch information and then entered into a binary tree.
|
||
; The binary tree is used to sort the patch list alpabetically. After it finishes,
|
||
; it disposes of all of the nodes of the tree.
|
||
;
|
||
; Patch Collator uses simple parsing techniques. It does not check whether or not the information
|
||
; is correct or not. Patch Collator will leave that for the AI group.
|
||
;
|
||
; Output will contain the information something like this...
|
||
;
|
||
; Files working on...
|
||
; ===================
|
||
; #1) Reading file PatchPlusROM.a
|
||
; Includes patch files for PatchPlusROM.a are as follows...
|
||
; #3) DrawPicturePatch.a
|
||
; #4) TEPatch.a
|
||
; #5) FontMgrPatch.a
|
||
; #6) MenuMgr.a
|
||
; #7) HMenuPatch.Install
|
||
; #2) Reading file PatchSEROM.a
|
||
; Includes patch files for PatchSEROM.a are as follows...
|
||
; #3) DrawPicturePatch.a
|
||
; #6) MenuMgr.a
|
||
; #7) HMenuPatch.Install
|
||
; #3) **Warning - could not open DrawPicturePatch.a
|
||
; #4) **Warning - could not open TEPatch.a
|
||
; #5) **Warning - could not open FontMgrPatch.a
|
||
; #6) **Warning - could not open MenuMgr.a
|
||
; #7) **Warning - could not open HMenuPatch.Install
|
||
; ====================================================================================================
|
||
; *****PATCH COLLATOR*****
|
||
; ====================================================================================================
|
||
;
|
||
; ** Column Condition:
|
||
; ** X means this trap is patched to fix another trap.
|
||
; Y means that this trap is being fixed by a trap ( possibly itself ).
|
||
;
|
||
; Patch List Condition Patch# Fix File Line# Date
|
||
; ====================================================================================================
|
||
;
|
||
; AsynchDrvrs Y #3 PatchPlusROM.a 2348 14Oct85
|
||
; AsynchDrvrs Y #42 PatchPlusROM.a 2302 14Oct85
|
||
; atalk:lap.a X #P019 PatchSEROM.a 2273 23Dec86
|
||
; atalk:nonres.a X #PA073 PatchSEROM.a 2276 2Mar87
|
||
; AutoInt1 X #21 PatchPlusROM.a 1700 01Jan1904
|
||
; BasicIO X #50 PatchPlusROM.a 2540 11Sep86
|
||
; BasicIO Y #50 PatchPlusROM.a 2540 11Sep86
|
||
; BTClose X #43 PatchPlusROM.a 2404 23Apr86
|
||
; BTClose Y #43 PatchPlusROM.a 2404 23Apr86
|
||
;
|
||
; Notice: The files that couldn't be opened will give a warning. This could have resulted in
|
||
; a typo or perhaps the file was not found in the directory.
|
||
;
|
||
;
|
||
;
|
||
;
|
||
;_______________________________________________________________________________________
|
||
|
||
FontManager PROC EXPORT
|
||
|
||
EXPORT InitFonts
|
||
EXPORT SetFontLock
|
||
EXPORT GetFontName
|
||
EXPORT FMSwapFont
|
||
EXPORT RealFont
|
||
EXPORT FontMetrics
|
||
EXPORT SetFScaleDisable
|
||
EXPORT SetFractEnable
|
||
EXPORT FMgrEnd
|
||
|
||
EXPORT FPointOne ; (so that first reference wil be seen.)
|
||
|
||
bugFix EQU 1
|
||
patch EQU 1
|
||
|
||
FoutCurStyle EQU FOutUnused ;post the current style used here.
|
||
|
||
NumTables EQU 12
|
||
WidListSize EQU NumTables*4
|
||
|
||
FMSwapTrap EQU $101 ;the FMSwapFont trap number for _GetTrapAddr
|
||
|
||
; format of a width table:
|
||
|
||
WidTabData EQU 0 ;256 fixed point widths
|
||
WidTabFont EQU 1024 ;(long) font handle used to generate this width table
|
||
WidthSExtra EQU WidTabFont+4 ;(long) fixed point space extra used for this table
|
||
WidthStyle EQU WidthSExtra+4 ;(long) fixed point extra due to style, used for this table
|
||
WidthFID EQU WidthStyle+4 ;(word) font family ID for this table
|
||
WidthFSize EQU WidthFID+2 ;(word) font size request that generated this table
|
||
WidthFace EQU WidthFSize+2 ;(word) face request that generated this table
|
||
WidthDevice EQU WidthFace+2 ;(word) device requested
|
||
WidthScales EQU WidthDevice+2 ;(8 bytes) scale factors requested on input
|
||
WidthAFID EQU WidthScales+8 ;(word) actual font family ID for this table
|
||
WidthFHand EQU WidthAFID+2 ;(long) font family handle for this table
|
||
WidthUsedFam EQU WidthFHand+4 ;(boolean) whether we used fixed point family widths
|
||
WidthAFace EQU WidthUsedFam+1 ;(byte) actual face produced (may differ for styled fonts)
|
||
WidthVOutput EQU WidthAFace+1 ;(word) vertical scale output value
|
||
WidthHOutput EQU WidthVOutput+2 ;(word) horizontal scale output value
|
||
WidthVFactor EQU WidthHOutput+2 ;(word) vertical scale output value
|
||
WidthHFactor EQU WidthVFactor+2 ;(word) horizontal scale output value
|
||
WidthASize EQU WidthHFactor+2 ;(word) actual size of font strike used
|
||
WidTabSize EQU WidthASize+2 ;total size of a width table.
|
||
|
||
|
||
|
||
; FOND format definition
|
||
|
||
FONDFlags EQU 0 ; 0 (word) Flags word for family
|
||
FONDFamID EQU FONDFlags+2 ; 2 (word) Family ID number
|
||
FONDFirst EQU FONDFamID+2 ; 4 (word) first character in font
|
||
FONDLast EQU FONDFirst+2 ; 6 (word) last character in font
|
||
FONDAscent EQU FONDLast+2 ; 8 (word) maximum Ascent expressed for 1 pt.
|
||
FONDDescent EQU FONDAscent+2 ; A (word) maximum Descent expressed for 1 pt.
|
||
FONDLeading EQU FONDDescent+2 ; C (word) maximum Leading expressed for 1 pt.
|
||
FONDWidMax EQU FONDLeading+2 ; E (word) maximum MaxWidth expressed for 1 pt.
|
||
FONDWTabOff EQU FONDWidMax+2 ;10 (long) Offset to width table
|
||
FONDKernOff EQU FONDWTabOff+4 ;14 (long) Offset to kerning table
|
||
FONDStylOff EQU FONDKernOff+4 ;18 (long) Offset to Style Mapping Table
|
||
FONDProperty EQU FONDStylOff+4 ;1C (12 words) contains style property info
|
||
FONDAssoc EQU FONDProperty+24 ;34 (variable length) Font Association Table.
|
||
|
||
FAssocSiz EQU 6 ;size of a font association table entry.
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; PROCEDURE InitFonts -- initialize the font manager data structures
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (InitFonts) (InitFonts)
|
||
;
|
||
|
||
InitFonts
|
||
IF bugFix THEN
|
||
MOVEQ #-1,D2 ;get some ones
|
||
CLR.W FOutError ;clear once at init time
|
||
ELSE
|
||
CLR.W FOutError ;clear once at init time
|
||
CLR.L FOutFontHandle ;may point to non-existent font, so clear
|
||
MOVEQ #-1,D2 ;get some ones
|
||
MOVE.W D2,FONDID ;init FOND cache
|
||
CLR.L LastFOND
|
||
ENDIF
|
||
BSR SetScreenDevice ;make the screen the default device
|
||
CLR.W CurFMDevice ;make the device 0
|
||
CLR.B FScaleDisable ;enable font scaling
|
||
CLR.B FractEnable ;for now, turn off fractWidths
|
||
ST FontFlag ;set to note that a call is not re-entrant
|
||
MOVE.W SPFont,ApFontID ;set up default font ID
|
||
ADDQ.W #1,ApFontID ;bump it by 1
|
||
MOVE.B #12,FMDefaultSize ;set up FMDefault Size
|
||
|
||
; allocate and initialize the width table in the system heap, if we haven't already
|
||
MOVE.L WidthTabHandle,D0 ;already got it?
|
||
BNE.S @4 ;if we have it, skip
|
||
|
||
MOVE.L #WidTabSize,D0 ;size of table
|
||
_NewHandle ,SYS ;new handle in sysHeap
|
||
BNE.S CantAllocWTab ;if an error, skip
|
||
|
||
MOVE.L A0,WidthTabHandle ;remember it
|
||
|
||
; allocate a width table list if there is room for them.
|
||
IF bugFix THEN
|
||
ELSE
|
||
CLR.L WidthListHand ;assume not enough memory for other tables.
|
||
CMP.W #2,MemTop ;are we in a small memory system?
|
||
BLS.S @4 ;yes, then forget the second width table handle.
|
||
ENDIF
|
||
MOVE.L #WidListSize,D0 ;size of table
|
||
_NewHandle ,SYS,CLEAR ;new handle in sysHeap, cleared
|
||
BNE.S @4 ;if an error, skip
|
||
MOVE.L A0,WidthListHand ;remember it
|
||
|
||
; Invalidate all of the extra width tables, if they exist.
|
||
|
||
@4
|
||
; set up swapFont jump table entry
|
||
IF patch THEN
|
||
MOVE #$101,D0
|
||
_GetTrapAddress
|
||
MOVE.L A0,JSwapFont
|
||
ELSE
|
||
MOVE.L $1204,JSwapFont ;set up the jump vector
|
||
ENDIF
|
||
|
||
BSR.S InValWidths ;invalidate all of the width tables.
|
||
|
||
; new system font logic to handle non-12 point, or non-Chicago system font.
|
||
|
||
MOVE.L OneOne,-(SP) ;scale factor denominator
|
||
MOVE.L OneOne,-(SP) ;scale factor numerator
|
||
CLR.L -(SP) ;clear face, need bits, device
|
||
CLR.L -(SP) ;pass system family, size
|
||
SUBQ #4,SP ;room for function result
|
||
PEA 4(SP) ;pass the address of the input record
|
||
_FMSwapFont
|
||
ADD #20,SP ;toss function result & input record
|
||
MOVE.L FOutFontHandle,RomFont0 ;salt away system font for backwards compat.
|
||
@skipRest
|
||
RTS
|
||
|
||
|
||
; we couldn't allocate the width table so issue the out-of-memory deepShit alert
|
||
; >> note that since there is no system font yet, this will flash the box repeatedly until the stack
|
||
; >> runs into something important. There must be a better way!
|
||
CantAllocWTab
|
||
MOVEQ #25,D0 ;out of mem code
|
||
_SysError ;self-destruct...
|
||
|
||
|
||
; Invalidate all of the extra width tables, if they exist.
|
||
|
||
InValWidths
|
||
; * restore purge state of old FOND first
|
||
MOVE.L LastFOND,A0
|
||
MOVE.B FONDstate,D0
|
||
CMP.B #$FF,D0
|
||
BEQ.S @skipUnintialized
|
||
_HSetState
|
||
@skipUnintialized
|
||
MOVEQ #-1,D2 ;get some ones
|
||
MOVE.L D2,LastSPExtra ;flag that we can't get a match next time <DLD 24-Oct-85>
|
||
|
||
IF bugFix THEN
|
||
MOVE.W D2,FONDID ;init FOND cache (bug fix: not specific to color)
|
||
ENDIF
|
||
|
||
MOVE.L WidthListHand,D0
|
||
BEQ.S InvalWidthTab
|
||
MOVE.L D0,A1
|
||
MOVE.L (A1),A1 ;handle->pointer
|
||
MOVEQ #NumTables-1,D1
|
||
@5
|
||
MOVE.L (A1)+,D0 ;get a handle from the table
|
||
BEQ.S InvalWidthTab ;end of table.
|
||
MOVE.L D0,A0
|
||
MOVE.L (A0),D0 ;was this handle purged?
|
||
BEQ.S @55
|
||
MOVE.L (A0),A0
|
||
MOVE.L D2,WidTabFont(A0) ;invalidate it
|
||
MOVE.W D2,WidthFID(A0) ;and invalidate requested font ID.
|
||
@55
|
||
DBRA D1,@5 ;until end of table.
|
||
|
||
; Invalidate the width table.
|
||
|
||
InvalWidthTab
|
||
MOVEQ #-1,D2 ;set up invalid value
|
||
BSR.S DerefWidthTab
|
||
MOVE.L D2,WidTabFont(A0) ;invalidate it
|
||
MOVE.W D2,WidthFID(A0) ;and invalidate requested font ID.
|
||
MOVE D2,CurFMFamily ;and avoid simple match
|
||
RTS
|
||
|
||
;common dereference
|
||
DerefWidthTab
|
||
MOVE.L WidthTabHandle,A0
|
||
MOVE.L (A0),A0 ;handle->pointer
|
||
RTS
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; FamSizeInD0 returns both the family and the high word and the size in the low word.
|
||
|
||
FamSizeInD0
|
||
MOVEQ #0,D1 ;zero high byte of size
|
||
MOVE (A3),D0 ;get the family
|
||
BNE.S @notSystem ;only system if it is zero
|
||
MOVE SysFontFam,D0 ;set up system family (could be zero, OK)
|
||
MOVE SysFontSize,D1 ;set up system size (less OK if zero)
|
||
BNE.S @sysSizeOK ;if nonzero, keep it
|
||
@notSystem
|
||
MOVE.B FMDefaultSize,D1 ;get default font size
|
||
BNE.S @sizeNonZero
|
||
MOVEQ #12,D1 ;if low memory is no help, hard code to 12
|
||
@sizeNonZero
|
||
CMP #1,D0 ;is the font the application font?
|
||
BNE.S @sysSizeOK ;if not, don’t change it
|
||
MOVE ApFontID,D0 ;change family to application family
|
||
@sysSizeOK
|
||
SWAP D0 ;save the family
|
||
MOVE fmInSize(A3),D0 ;get current size
|
||
BNE.S @notSizeZero ;if nonzero, leave alone
|
||
MOVE D1,D0 ;else use either SysFontSize or FMDefaultSize
|
||
@notSizeZero
|
||
RTS
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
; A6 offsets for SwapFont
|
||
copyInput EQU -16 ;place to hold copy of CurFMInput
|
||
styleID EQU copyInput-4 ;saved style and ID from FOND (set up in GoLoadStrike)
|
||
paramBlk EQU styleID-ioQElSize
|
||
saveMap EQU paramBlk-2 ;the application’s resource map in the system sub case
|
||
fwidStyle EQU saveMap-2 ;the style of the best width table found in the FOND
|
||
stackFrame EQU fwidStyle ;size of stack frame
|
||
|
||
;
|
||
; FUNCTION FMSwapFont(inRec:FontInputRecord):^FontOutputRecord
|
||
;
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (FMSwapFont) (FMSwapFont)
|
||
;AppleSystemPatch PatchIIROM.a 27Aug87 #PABM253 (GetHandleSize) (RealFont)
|
||
;
|
||
; FMSwapFont is the heart of the font manager. It receives an input record
|
||
; from QuickDraw specifying the font, face, device and scale of the requested
|
||
; font and figures out the best set of bits to load and return in the output
|
||
; record. It is optimized so that if the request is the same as the previous
|
||
; one, it returns as fast as it can.
|
||
|
||
; Some init conditions are rolled in from patches...
|
||
;
|
||
; To (try to) understand FontFlag, see the comments at SubFont, far, far below.
|
||
;
|
||
FMSwapFont
|
||
|
||
; Check FontFlag to see if we got here through SysError first.
|
||
LEA FMgrOutRec,A0 ;get pointer to our output record
|
||
MOVE.L A0,8(SP) ;return it as the result
|
||
MOVEQ #-1,D2 ;common constant to invalidate globals
|
||
CMP.L LastSpExtra,D2
|
||
BEQ GoDifFont
|
||
ADDQ.B #1,FontFlag ;if not a re-entrant call, this sets to zero
|
||
BEQ.S @notReentrant
|
||
BSR.S InvalWidthTab ;don’t use the current cache; may be incomplete
|
||
|
||
; Here we know that the call to LoadResource failed, the disk switch hook is trying to go up, or a real
|
||
; SysError occured.
|
||
|
||
CMP.B #9,FontFlag ;are all substitutions exhausted ?
|
||
BEQ GoTryChicago ;if so, go straight for the ROM font
|
||
BGT FMSwapDone ;if that didn’t work, this just return the last record
|
||
MOVE.B #8,FontFlag ;set to next re-entrant range.
|
||
@notReentrant
|
||
|
||
; the most important thing to do is to see if the input record is the same
|
||
; as it was last time, as fast as we can
|
||
|
||
MOVE.L 4(SP),A0 ;keep input record pointer in A3
|
||
LEA CurFMInput,A1 ;point at last request
|
||
|
||
CMPM.L (A0)+,(A1)+ ;the same?
|
||
BEQ.S @okFamSize ;if so, skip
|
||
MOVE.L A3,-(SP) ;maybe just substitution
|
||
MOVE.L 8(SP),A3 ;set up input record for utility
|
||
BSR.S FamSizeInD0 ;returns family, size
|
||
MOVE.L D0,D2 ;save input record, substituted
|
||
LEA CurFMInput,A3 ;maybe actuals need subbing as well
|
||
BSR.S FamSizeInD0 ;get last family, size
|
||
MOVE.L (SP)+,A3 ;restore
|
||
CMP.L D2,D0 ;the same?
|
||
BNE.S GoDifFont
|
||
MOVE.L -4(A0),-4(A1) ;jam original so next time is fast
|
||
@okFamSize
|
||
CMPM.L (A0)+,(A1)+ ;face, needbits, device the same?
|
||
BEQ.S @okFaceBitsDev ;if so, fine, continue fast case
|
||
; ! assume for now that I can get away without matching needBits
|
||
MOVE.L -(A0),D0 ;get the request face, needBits, device
|
||
MOVE.L -(A1),D1 ;check that against the last accessed face, bits, dev.
|
||
EOR.L D0,D1 ;set the bits that are different
|
||
AND.L #$FF00FFFF,D1 ;clear the needBits part
|
||
BNE.S GoDifFont ;if more is different, go handle it
|
||
MOVE.L (A0)+,(A1)+ ;make fast for next time, continue fast case
|
||
@okFaceBitsDev
|
||
CMPM.L (A0)+,(A1)+ ;numer the same?
|
||
BNE.S GoDifFont ;if not, skip
|
||
|
||
CMPM.L (A0)+,(A1)+ ;denom the same?
|
||
BNE.S GoDifFont ;if so, we're cool!
|
||
|
||
; ugh -- now we have to pull SpExtra out of the port to see if
|
||
; that changed. If not, we're cool.
|
||
; Believe it or not, it is possible that QuickDraw is not around at all, so test first.
|
||
|
||
TST.B QDExist ;is QuickDraw around
|
||
BMI.S StraightLineCP
|
||
MOVE.L grafGlobals(A5),A0 ;get grafGlobals
|
||
MOVE.L thePort(A0),D0 ;get thePort
|
||
BEQ.S StraightLineCP ;if no port, don’t check space extra
|
||
MOVE.L D0,A0
|
||
@checkLastSp
|
||
MOVE.L LastSpExtra,D0 ;get spaceExtra <DLD 24-Oct-85>
|
||
CMP.L SpExtra(A0),D0 ;did it change? <DLD 24-Oct-85>
|
||
BEQ.S StraightLineCP ;if not, skip
|
||
|
||
; spaceExtra changing is not such a big deal; we don't have to recalculate
|
||
; everything. Dive in at the right spot...
|
||
LINK A6,#stackFrame
|
||
CLR saveMap(A6) ;in case substitution must switch res. maps
|
||
CLR fwidStyle(A6) ;just in case, remember no styled widths have been found
|
||
MOVEM.L D3-D7/A2-A4,-(SP) ;save work registers
|
||
MOVE.L 8(A6),A3 ;get input pointer
|
||
SUBQ.B #2,FontFlag ;set up substitution position to try again.
|
||
BRA AdjustSpace ;dive in...
|
||
|
||
; the request is different from the last one, so do things the slow way
|
||
|
||
GoDifFont
|
||
BRA.S DifFont ;go handle it
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; Hurray! the font was the same as last time so we can return right away. The
|
||
; only thing left to do is to make sure the font wasn't purged. The master pointer can only contain
|
||
; a real live font or NIL. No need to check to see if the resource bits are set or if the master pointer
|
||
; is part of the free chain or if the handle has been reused since any calls to OpenResFile, CloseResFile
|
||
; and ReleaseResource have invalidated any cached handle state.
|
||
|
||
; A large scale change made here is to branch to DifFont if the font can not be loaded. This allows the
|
||
; same substitution to be used by all. Before, the system font was loaded instead, using the CurFMInput
|
||
; record. The new code is possibly disasterous since CheckPurged is called at the tail end of DifFont, so
|
||
; the space extra only special case can use the same code as the long way around. I need to make sure
|
||
; that DifFont only gets this far if the font has been successfully loaded, and no further purging sort of
|
||
; operations have occurred.
|
||
|
||
StraightLineCP
|
||
SUBQ.B #2,FontFlag ;set up substitution position to try again.
|
||
|
||
CheckPurged
|
||
MOVE.L FOutFontHandle,A0 ;get the font handle.
|
||
TST.L (A0)
|
||
BNE.S FMSwapDone
|
||
MOVE.L A0,-(SP) ;push it
|
||
MOVE.W #MapTrue,ROMMapInsert ;get it from ROM if possible <10 Jul 85>
|
||
_LoadResource ;make sure its loaded
|
||
CMP.B #-1,FontFlag ;hit disk-switch?
|
||
BEQ.S GoDifFont ;other data is inconsistent so start over.
|
||
TST.L (A0) ;still NIL?
|
||
BEQ.S GoDifFont ;if so, in trouble
|
||
BSR BuildCharTable ;need to rebuild character table
|
||
|
||
; all done with FMSwapFont so restore registers and return to our caller
|
||
|
||
FMSwapDone
|
||
|
||
; we must re-establish widthPtr each time we are called, as the heap might
|
||
; have been compacted. Note that this is for backwards compatability only.
|
||
|
||
MOVE.L WidthTabHandle,A0
|
||
MOVE.L (A0),WidthPtr ;assume color QD needs this no more.
|
||
ST FontFlag ;no more worry about re-entrancy
|
||
|
||
; If returning to previous font manager call (via LoadResource, GetResource, etc.), will need to check
|
||
; FontFlag to see if it is -1; if so, start substitution all over since state is no good.
|
||
|
||
MOVE.L (SP)+,A0 ;get return address
|
||
ADDQ #4,SP ;strip parameter
|
||
JMP (A0) ;return to caller
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; Utility called by DoMapFont when the correct widths were found in the width cache. It is called twice
|
||
; to set up FOutNumer h & v, FScaleVFact & FScaleHFact. A1 first points to widthVOutput in the FOND.
|
||
; D1 is either 0 (for v) or 2 (for h).
|
||
;————————————————————————————————————————————————————————————————————
|
||
SetUpScale
|
||
IF patch THEN
|
||
IF onMac THEN
|
||
JMP $40EA96
|
||
ELSEIF onMacPP THEN
|
||
JMP $41931C ; *NB Patch* need addresses for both SE and Plus.
|
||
ENDIF
|
||
ELSE
|
||
LEA fmOutNumer+FOutRec,A0 ;set up the scale factor in the output record.
|
||
MOVE.W (A1)+,0(A0,D1) ;save @ FOutNumer. (FOutDenom is always 256.)
|
||
|
||
LEA FScaleVFact,A0 ;also set up scale factor in low memory.
|
||
MOVEQ #0,D0 ;clear high word (unsigned?)
|
||
MOVE.W 2(A1),D0 ;widthVFactor or widthHFactor
|
||
ASL.L #8,D0 ;adjust 8.8 number to 16.16
|
||
ADD D1,D1 ;double to 0 or 4.
|
||
NEG.W D1 ;make 0 or -4. (Low memory is h, v; table is v, h)
|
||
MOVE.L D0,0(A0,D1) ;save @ FScaleVFact, then FScaleHFact
|
||
RTS
|
||
ENDIF
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; Given a handle to a FONT, NFNT or FOND in A0, DeRefResource loads it if it has been purged (skipping
|
||
; the trap call if it is already in memory.) A0 is set on output to point to the resource, or equals NIL
|
||
; if the call to LoadResource fails. The Z flag is set if the call to load resource failed.
|
||
;————————————————————————————————————————————————————————————————————
|
||
|
||
DeRefResource
|
||
TST.L (A0) ;see if it is already loaded.
|
||
BNE.S alreadyLoaded ;if so, do nothing.
|
||
MOVE.L A0,-(SP) ;push it
|
||
MOVE.W #MapTrue,ROMMapInsert ;get it from ROM if possible <10 Jul 85>
|
||
_LoadResource ;make sure its loaded
|
||
CMP.B #-1,FontFlag ;hit disk-switch?
|
||
BEQ.S badLoad ;other data is inconsistent so start over.
|
||
TST.L (A0) ;still NIL?
|
||
BEQ.S badLoad ;if so, in trouble
|
||
alreadyLoaded
|
||
MOVE.L (A0),A0 ;handle -> pointer
|
||
RTS
|
||
badLoad
|
||
BRA Pop4SubFont ;start substituting (throw away return address)
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
; DifFont - handle a font or style change.
|
||
;
|
||
; We reach this point when the family, size, scale or device has been changed, which usually means that
|
||
; we have to load in some new bits. The first thing to do is see if the device changed and, if it has, ask it
|
||
; for a new style table and dots/inch values.
|
||
;
|
||
;———————————————————————————————————————————————————————————————————
|
||
|
||
DifFont
|
||
LINK A6,#stackFrame ;might as well use locals as locals.
|
||
CLR saveMap(A6) ;in case substitution must switch res. maps.
|
||
CLR fwidStyle(A6) ;just in case, remember no styled widths have been found
|
||
MOVEM.L D3-D7/A2-A4,-(SP) ;save work registers
|
||
|
||
MoreDifFont
|
||
MOVE.L 8(A6),A0 ;pick up request pointer
|
||
LEA copyInput(A6),A1
|
||
MOVEQ #$10,D0
|
||
_BlockMove ;make copy of request
|
||
MOVE.L A1,A3
|
||
|
||
MOVE.B fmInFace(A3),FOutCurStyle ;set up desired style
|
||
MOVE.W fmInDevice(A3),D0 ;get device in request
|
||
CMP.W CurFMDevice,D0 ;did it change?
|
||
BEQ.S @sameDevice ;if not, we're cool
|
||
BSR SetNewDevice ;otherwise, read in the new stuff
|
||
@sameDevice
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
;
|
||
; The TryAgain entry point is used if no size/style variant of the requested font was found. SubFont has
|
||
; changed the family field and restored the size field from the original input record before entering here.
|
||
;
|
||
;———————————————————————————————————————————————————————————————————
|
||
TryAgain
|
||
BSR FamSizeInD0
|
||
MOVE.L D0,(A3) ;save the size, family
|
||
; remember that copy has needBits cleared, but spline code (??) should check A6 input record !!!
|
||
CLR.B fmInNeedBits(A3)
|
||
LEA FontFlag,A4 ;we save a word here.
|
||
CMP.B #6,(A4) ;did we just substitute the ROM font?
|
||
BLT.S @skipROMFamily ;if not, all is well
|
||
CLR (A3) ;zero family, but leave substituted size
|
||
@skipROMFamily
|
||
|
||
; if we got here from the shortcut exact match or space extra only change, and LoadResource of
|
||
; the font failed, then FontFlag is set to -2.
|
||
|
||
TST.B (A4) ;test FontFlag for -2
|
||
BPL.S DoMapFont ;if 0 or greater, no problem
|
||
BSR InvalWidthTab ;invalidate WidthTabHandle
|
||
CLR.B (A4) ;advance to real substitution
|
||
|
||
; Use the info from the old width table if it applies.
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
; DoMapFont searches handles pointed to by the width list for a table of widths matching the font
|
||
; requested by the input pointer.
|
||
;
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (DoMapFont) (DoMapFont)
|
||
;
|
||
; Registers used:
|
||
; D0 = size of width table, scratch D1 = scratch D2 = last purged handle entry offset
|
||
; D3 = last invalidated entry offset D4 = table full flag D5 = offset into entry list
|
||
; D6 = call MapFont flag D7 = last nonpurged offset A0 = scratch
|
||
; A1 = scratch A2 = A3 = input pointer
|
||
; A4 = width list handle, pointer
|
||
;
|
||
; Significant changes made since the Macintosh + ROM:
|
||
;
|
||
; 12-Aug-86 CRC Details, details…
|
||
; The algorithm for determining which entry to use was:
|
||
; Check list until match, or entry = 0, or entry has been purged, or the end of the list is reached.
|
||
; If an entry was purged, reallocate it and use it.
|
||
; If entry = 0, allocate it and use it.
|
||
;
|
||
; The algorithm is now:
|
||
; Check list until match or entry = 0 or the end of the list is reached.
|
||
; if no match, use the last invalidated entry in the list.
|
||
; if memory is not full:
|
||
; if no invalidated entry, reallocate the last purged entry in the list.
|
||
; if no purged entry, and the last entry = 0, allocate a new entry at the end of the list.
|
||
; if memory is full or the list is full:
|
||
; reuse the last nonpurged entry in the list.
|
||
; if there isn’t a nonpurged entry then we’re out of luck; don’t use cache.
|
||
; if a memory allocation call fails, then the system heap is in bad shape; don’t use cache.
|
||
;
|
||
; The actual size and font are stored in the width table instead of 0 or applFont.
|
||
;
|
||
; NewHandle, ReallocHandle recover if an error is returned.
|
||
;
|
||
; Entries in queue are rotated so that list is ordered most recently accessed to least recently
|
||
; accessed. If the system heap has room for all twelve elements, the least recently accessed is
|
||
; reused first. Otherwise, the Memory Manager roving purge pointer spins the wheel of fortune to
|
||
; decide who is purged (but only if some other process allocates heap space, or if the system heap
|
||
; is sufficiently fragmented.)
|
||
;
|
||
; Just for grins, all local branches are forward except for branches to the tops of loops.
|
||
;
|
||
; Any newly allocated or reused width table has the font handle and family ID fields invalidated to
|
||
; allow optimization of the remainder of the table fill-in code.
|
||
;
|
||
;———————————————————————————————————————————————————————————————————
|
||
|
||
DoMapFont
|
||
MOVE.L WidthListHand,D0 ;do we have any spare width tables?
|
||
BEQ.S @shortSkip ;if not, then skip this nonsense.
|
||
|
||
; Check if the width-table cache is still valid. <18-Oct-85>
|
||
|
||
MOVEQ #-1,D2 ;handy invalidation constant
|
||
CMP.L LastSpExtra,D2 ;invalidated through normal means or switcher?
|
||
BEQ.S @invalAll
|
||
|
||
CMP CurFMFamily,D2 ;just reuse WidthTabHandle?
|
||
BNE.S @notInvalid
|
||
BRA.S @shortSkip
|
||
@invalAll
|
||
BSR InvalWidths ;invalidate all of the width tables.
|
||
@shortSkip
|
||
BRA @skipCache ;
|
||
|
||
; We know that there has been some change. Search the list of width tables for a match.
|
||
|
||
@notInvalid
|
||
MOVE.L D0,A4 ;get the width list handle.
|
||
MOVE.L (A4),A4
|
||
MOVEQ #-1,D2 ;no purged handles found so far.
|
||
MOVEQ #-1,D3 ;no invalidated entries found so far.
|
||
SF D4 ;assume that table is not full.
|
||
MOVEQ #-4,D5 ;list entry counter is incremented at the top of loop.
|
||
SF D6 ;do call MapFont
|
||
MOVEQ #-1,D7 ;no nonpurged handles found so far.
|
||
|
||
; Check each list entry to see if it has been allocated, or if the table has purged.
|
||
|
||
@loopTop
|
||
ADDQ #4,D5 ;advance to next entry in width table handle
|
||
MOVE.L (A4),D1 ;get a possible width table handle.
|
||
BEQ @outOfLoop ;if none, create a new entry.
|
||
MOVE.L D1,A0
|
||
MOVE.L (A0),D0 ;get the master pointer.
|
||
BEQ @rememberPurge ;skip if it has been purged.
|
||
MOVE D5,D7 ;remember that this one was not purged.
|
||
MOVE.L D0,A1 ;we are pointing at the table now.
|
||
|
||
; We know that the device and scales match. But does the old table match the requested style?
|
||
|
||
MOVEQ #3,D1 ;number of longs to check - 1
|
||
MOVE.L A3,A0 ;copy the input pointer
|
||
LEA WidthFID(A1),A1 ;point to old width's info.
|
||
CMP #-1,(A1) ;check to see if it is valid.
|
||
BNE.S @valid ;skip if valid.
|
||
MOVE D5,D3 ;remember offset to invalid entry
|
||
@valid
|
||
CMPM.L (A0)+,(A1)+ ;does family, size; face, needbits, device;
|
||
DBNE D1,@valid ; numer; denom match?
|
||
BNE.S @loopBottom ;
|
||
|
||
; We already have the font handle (from the old width table), so skip most of MapFont.
|
||
|
||
ST D6 ;don’t call MapFont
|
||
MOVE (A1),D0 ;get new font family ID
|
||
CMP FONDID,D0 ;different from old one?
|
||
BEQ.S @sameFOND ;if not, fond globals are already set up
|
||
MOVE.B FONDState,D0 ;get old FOND state
|
||
MOVE.L LastFOND,A0 ;maybe zero; if so, HSetState will reject
|
||
_HSetState ;restore purge state
|
||
|
||
MOVE.L (A4), A0 ; Get the Width Table handle <PMAB528>
|
||
_HNoPurge ; Make the Width Table non-purgeable <PMAB528>
|
||
|
||
MOVE (A1)+,D0 ;get new FOND ID
|
||
MOVE D0,FONDID ;save it
|
||
MOVE.L (A1)+,A0 ;get new FOND handle
|
||
MOVE.L A0,LastFOND ;save it
|
||
BEQ.S @noFOND
|
||
BSR DerefResource ;load it if it has purged
|
||
MOVE.B (A0),SaveFondFlags ;save the high byte of the FOND flags.
|
||
MOVE.L LastFOND,A0
|
||
_HGetState ;get the purge state
|
||
MOVE.B D0,FONDState ;preserve it until the next change
|
||
_HNoPurge ;and make the font nonpurgable
|
||
|
||
MOVE.L WidthListHand, A4 ; Get the list handle of Width Tables <PMAB528>
|
||
MOVE.L (A4), A4 ; Pointer to Width Table Handles <PMAB528>
|
||
ADD D5, A4 ; Add Offset of current Width Table <PMAB528>
|
||
MOVE.L (A4), A1 ; Handle to Width Table <PMAB528>
|
||
MOVE.L (A1), A1 ; Width Table ptr <PMAB528>
|
||
LEA WidthUsedFam(A1), A1 ; Load the address of the WidthUsedFam <PMAB528>
|
||
|
||
BRA.S @noFOND ;skip skip
|
||
@sameFOND
|
||
ADDQ #6,A1 ;skip over FOND ID, handle
|
||
@noFOND
|
||
MOVE.B (A1)+,UsedFWidths ;remember if we used family widths.
|
||
|
||
; We are changing back to an old style, so set up FOutFontHandle from our width.
|
||
|
||
MOVE.B (A1)+,FOutCurStyle ;set up real style (computed along with width table).
|
||
|
||
MOVEQ #0,D1
|
||
BSR SetUpScale ;set up the vertical scale factor and output.
|
||
MOVEQ #2,D1
|
||
BSR SetUpScale ;set up the horizontal scale factor and output.
|
||
|
||
; If we really want an expanded version, see if it already exists.
|
||
|
||
MOVE.L (A4),A0 ;get width handle.
|
||
MOVE.L (A0),A1 ;pointer to width table.
|
||
MOVE.L WidTabFont(A1),A1 ;corresponding font handle.
|
||
MOVE.L A1,FOutFontHandle ;get the font handle.
|
||
BRA.S @toSkipNew ;insert width handle in list.
|
||
|
||
; This entry did not match the request, so go on to the next one.
|
||
|
||
@rememberPurge
|
||
MOVE D5,D2 ;remember that this one was purged.
|
||
@loopBottom ;
|
||
ADDQ #4,A4 ;bump the list pointer.
|
||
CMP.W #(NumTables-1)*4,D5 ;done with the table yet?
|
||
BLO @loopTop ;try for a match on the next one in the list.
|
||
|
||
; end of loop
|
||
ST D4 ;remember that the table was full.
|
||
SUBQ #4,A4 ;point back at the one we want to use.
|
||
|
||
@outOfLoop
|
||
|
||
; if no exact match was found, check the existing WidthTabHandle to see if it is already invalid.
|
||
|
||
MOVE.L WidthTabHandle,A1 ;get address of handle
|
||
MOVE.L (A1),A1 ;get master pointer
|
||
CMP.W #-1,WidthFID(A1) ;has it been marked invalid?
|
||
BEQ.S @skipCache ;it is all ready to use.
|
||
|
||
EXG D3,D5 ;set up invalid position, preserve end of table.
|
||
TST D5 ;was an invalid table found?
|
||
BPL.S @reuseIt ;if so, skip purge check.
|
||
MOVE.L #WidTabSize,D1 ;get size of a table, in case we must allocate it.
|
||
IF bugFix THEN
|
||
_MaxBlock ,SYS ;better than FreeMem; unfortunately, didn’t know for Aladdin ROM
|
||
ELSE
|
||
MOVE.L TheZone,A1
|
||
MOVE.L SysZone,TheZone
|
||
_FreeMem ;get the total free space in the system heap.
|
||
MOVE.L A1,TheZone
|
||
ENDIF
|
||
CMP.L D1,D0 ;is there enough room?
|
||
BLE.S @useNonpurged ;if not, use the last nonpurged entry in the list.
|
||
MOVE.L D1,D0 ;set up size to allocate.
|
||
MOVE D2,D5 ;was a purged handle found (to be missing)?
|
||
BPL.S @reuseIt ;if so, since we have enough memory, reuse it.
|
||
TST.B D4 ;is the table full?
|
||
BNE.S @useNonpurged ;if so, re-use nonpurged entry.
|
||
|
||
; We are beyond all list entries, so create a new one.
|
||
|
||
MOVE D3,D5 ;restore end of table position.
|
||
_NewHandle ,SYS ;_NewHandle in system heap.
|
||
BNE.S @skipCache ;use it only if allocation successful.
|
||
BRA.S @reuseIt ;reset width list pointer since it may have moved.
|
||
@useNonpurged
|
||
MOVE D7,D5 ;last nonpurged entry.
|
||
BMI.S @skipCache ;if not one, all out of options.
|
||
@reuseIt
|
||
MOVE.L WidthListHand,A4 ;get the width list handle again.
|
||
MOVE.L (A4),A4 ;since it may have moved.
|
||
LEA 0(A4,D5),A4 ;determine list entry address.
|
||
MOVE.L (A4),D1 ;get the master pointer.
|
||
BEQ.S @newWidthTable ;if zero, just created; skip purge test.
|
||
MOVE.L D1,A0 ;get the master pointer.
|
||
TST.L (A0) ;has it been purged?
|
||
BNE.S @newWidthTable ;if non-purged, mark as invalid.
|
||
|
||
; We found a purged list entry, so let's re-allocate it.
|
||
|
||
_ReAllocHandle
|
||
BNE.S @skipCache ;it failed, so nothing can be cached.
|
||
BRA.S @reuseIt ;reset width list pointer since it may have moved.
|
||
|
||
; If ReallocHandle or NewHandle fail, then there is no room to cache anything (since all other cache
|
||
; members would have purged to allow ReallocHandle or NewHandle to succeed).
|
||
|
||
; At this point and at the entry point skipNew, A0 is the handle to be
|
||
; installed at the front of the table, A4 points to the entry position being reused, and D5 is the offset
|
||
; from the front of the table to the reused position.
|
||
|
||
@newWidthTable
|
||
@toSkipNew
|
||
BRA.S @skipNew ;dive in.
|
||
|
||
@skipNext
|
||
MOVE.L -(A4),4(A4) ;move previous entry to this one.
|
||
@skipNew
|
||
SUBQ #4,D5 ;see if this is the first entry.
|
||
BPL.S @skipNext ;if so, nothing to do.
|
||
@swapHandles
|
||
MOVE.L WidthTabHandle,D1 ;save current handle - it's old now.
|
||
MOVE.L A0,WidthTabHandle ;save it in widthTabHandle.
|
||
_HNoPurge ;the current handle can't purge.
|
||
MOVE.L D1,(A4) ;save old handle in the front of the list.
|
||
MOVE.L D1,A0
|
||
_HPurge ;now it can purge if it wants.
|
||
|
||
; check to see if font is already figured out and installed
|
||
|
||
TST.B D6 ;call MapFont?
|
||
BNE.S GotFontHandle ;don’t bother if the widths were found
|
||
|
||
; call MapFont to do all the hard work, installing a font in the output record
|
||
|
||
@skipCache
|
||
; Invalidate the new table entry.
|
||
BSR InvalWidthTab
|
||
BSR MapFont ;figure out font and install it
|
||
|
||
|
||
;——————————————————————————————————————————————————————————
|
||
GotFontHandle
|
||
MOVE.L FOutFontHandle,A0 ;get the current font handle
|
||
BSR DeRefResource ;load resource who's handle is in A0.
|
||
|
||
; set up ascent, descent, etc...
|
||
|
||
TST.B FScaleDisable ; if scaling disabled, do new way
|
||
BNE.S newSetupHeight
|
||
|
||
LEA FOutAscent,A1 ;point to the info section
|
||
MOVE.B FAscent+1(A0),(A1)+ ;copy ascent
|
||
MOVE.B FDescent+1(A0),(A1)+ ;copy descent
|
||
MOVE.B FWidMax+1(A0),(A1)+ ;copy max width
|
||
MOVE.B FLeading+1(A0),(A1) ;copy leading
|
||
BRA.S DoStyle
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; ByteScale, ByteHScale are utility routines used to figure the font metrics for this font.
|
||
; FScaleVFact contains the nice factor to allow scaling to be disabled so that QD can do no or easy bitmap
|
||
; scaling. The value to be scaled is passed in D0, and scaled by the value in D1.
|
||
;————————————————————————————————————————————————————————————————————
|
||
ByteScale
|
||
MOVE.L FScaleVFact,D1
|
||
ByteHScale
|
||
EXT D0 ;fix-ize the byte in D0
|
||
SWAP D0
|
||
CLR D0 ;clear fract
|
||
MOVEM.L D0-D3/A0-A1,-(SP) ;D0, D1are operands; D2, D3 make room for results,
|
||
;preserves A0, A1.
|
||
_FixMul ;
|
||
_FixRound
|
||
MOVE (SP)+,D0 ;get result in low byte
|
||
ADDQ #2,SP ;throw away the other half of D3
|
||
MOVEM.L (SP)+,A0-A1 ;restore registers
|
||
MOVE.B D0,(A1)+ ;save it in FMgrOutRec
|
||
RTS
|
||
|
||
newSetupHeight
|
||
LEA FOutAscent,A1 ;point to the info section
|
||
MOVE.B FAscent+1(A0),D0
|
||
BSR.S ByteScale ;copy integer ascent
|
||
MOVE.B FDescent+1(A0),D0
|
||
BSR.S ByteScale ;copy descent
|
||
MOVE.B FWidMax+1(A0),D0 ;maxwidth needs a horizontal factor adjustment.
|
||
MOVE.L FScaleHFact,D1
|
||
BSR.S ByteHScale ;copy max width
|
||
MOVE.B FLeading+1(A0),D0
|
||
BSR.S ByteScale ;copy leading
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
; At this point, we have the proper bits but the style parameters are wrong.
|
||
; Fill out the style record using a table supplied by the current device
|
||
|
||
DoStyle
|
||
MOVE.B FOutCurStyle,D1 ;get style byte
|
||
|
||
LEA FOutBold,A0 ;point at style part of output record
|
||
CLR.L (A0)+ ;set everything to 0
|
||
CLR.W (A0)+ ;clear some more
|
||
CLR.B (A0)+ ;clear seven bytes total
|
||
|
||
; special case the most common case -- plain text (ie, style byte is 0)
|
||
|
||
TST.B D1 ;plain?
|
||
BEQ.S CheckWTable ;if so, skip the loop
|
||
|
||
; we must fill out the style record the hard way, by looping through the
|
||
; driver-supplied style definition table
|
||
|
||
MOVEQ #0,D2 ;clear high part for indexing
|
||
LEA FMStyleTab,A1 ;point to the style table
|
||
MOVEQ #6,D0 ;consider 7 bits worth
|
||
LEA FOutBold,A0 ;point to style params
|
||
@fmStyloop
|
||
MOVE.B (A1)+,D2 ;get index
|
||
MOVE.B (A1)+,D3 ;get field increment
|
||
MOVE.B (A1)+,D4 ;get extra increment
|
||
|
||
LSR #1,D1 ;examine next style bit
|
||
BCC.S @nextSBit ;if its off, don't bother
|
||
|
||
ADD.B D3,0(A0,D2) ;increment proper style param
|
||
ADD.B D4,FOutExtra ;also increment extra
|
||
@nextSBit
|
||
DBRA D0,@fmStyloop ;loop till done
|
||
|
||
; special case underlining since it doesn't fit into our model
|
||
|
||
BTST #ULineBit,FOutCurStyle ;underlining on?
|
||
BEQ.S CheckWTable ;if not, skip
|
||
|
||
LEA FOutULOffset,A0 ;point to underline parameters
|
||
MOVE.B (A1)+,(A0)+ ;copy the three underline parameters
|
||
MOVE.B (A1)+,(A0)+ ;copy second byte
|
||
MOVE.B (A1)+,(A0)+ ;copy third byte
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; Now the style is all set up so its time to make sure the width table is cool. First check to see if the
|
||
; widths were already cached, so we can skip the most time-consuming part of the work.
|
||
|
||
CheckWTable
|
||
|
||
; These tests decide to use either the integral style extra provided by the Font Manager, or the
|
||
; fractional style extra in the FOND.
|
||
|
||
MOVE.L LastFond,D0 ;check if there is a last FOND.
|
||
BEQ MakeITab ;if not, style extra can’t be fractional.
|
||
|
||
TST.B FDevDisable ;set if the device would prefer the FOND style extra.
|
||
BNE.S @skipDevice
|
||
|
||
TST.B fmInDevice(A3) ;if the device is not the screen, it can supply it’s
|
||
BNE MakeITab ; own style widths, so skip looking at the FOND widths.
|
||
@skipDevice
|
||
BTST #5,saveFondFlags ;set if fractional style extra is never from FOND.
|
||
BNE.S MakeITab
|
||
|
||
BTST #4,saveFondFlags ;set if fractional style extra is always from FOND.
|
||
BNE.S @computeFractExtra ; <06Nov85>
|
||
|
||
TST.B FractEnable ;set if application allows fractional spacing
|
||
BEQ.S MakeITab ;if not, don’t figure fractional style extra from FOND. <06Nov85>
|
||
|
||
@computeFractExtra ;
|
||
|
||
; We can only get this far if the FOND has valid style extra entries (part of the FOND flags)?
|
||
; Next, compute the fixed point extra into D6 when we do have a family definition record present.
|
||
|
||
MOVE.L D0,A0 ;get the last fond.
|
||
BSR DeRefResource ;load resource who's handle is in A0.
|
||
|
||
; But wait, maybe this FOND is an empty FOND created by Font/DA Mover. If so, the FONDLast field
|
||
; will contain a zero.
|
||
|
||
TST FONDLast(A0) ;see if last character is zero.
|
||
BEQ.S MakeITab ;if so, do not calculate style here.
|
||
|
||
LEA FONDProperty(A0),A0 ;point to start of table
|
||
|
||
MOVE.W (A0)+,D6 ;get plain extra
|
||
EXT.L D6
|
||
|
||
; If the FOND has a width table with a style already calculated in it, it is not necessary to figure out the
|
||
; style extra for the styles already contained in the widths. Earlier, in GotEntry, a style with the correct
|
||
; widths found was saved in a local.
|
||
|
||
MOVE.B FOutCurStyle,D1 ;get style byte
|
||
BEQ.S @gotFractExtra ;if plain, skip the loop
|
||
BTST #6,saveFondFlags ;does this FOND have width tables at all?
|
||
BNE.S @noStyleInWidths ;if set (like for Courier) there are no width tables in FOND
|
||
MOVE fwidStyle(A6),D0 ;get style of widths already found
|
||
NOT D0 ;use as mask,
|
||
AND D0,D1 ;to turn off any style attributes already in widths
|
||
|
||
@noStyleInWidths
|
||
|
||
; we must fill out the style record the hard way, by looping through the
|
||
; driver-supplied style definition table
|
||
|
||
MOVEQ #7,D0 ;consider 8 bits worth
|
||
@exStyloop
|
||
MOVE.W (A0)+,D2 ;get extra value
|
||
|
||
LSR #1,D1 ;examine next style bit
|
||
BCC.S @nextExBit ;if its off, don't bother
|
||
|
||
; here we can add Adobe fix to look for funny sign bit sort of negative number
|
||
|
||
CMP #$8FFF,D2 ;is it -7.001 or smaller?
|
||
BGT.S @doNormalAdd
|
||
BCLR #15,D2 ;throw away sign bit
|
||
NEG D2 ;make into a normal two’s complement number
|
||
@doNormalAdd
|
||
EXT.L D2
|
||
ADD.L D2,D6 ;add it in
|
||
@nextExBit
|
||
DBRA D0,@exStyloop ;loop till done
|
||
@gotFractExtra
|
||
ASL.L #4,D6 ;adjust 4.12 to 16.16 fixed point
|
||
|
||
SUBQ #6,SP ;space for FixMul, FixRound results
|
||
CLR.W -(SP) ;fraction part zero.
|
||
BSR DerefWidthTab ;get pointer to width table in A0
|
||
MOVE.W WidthASize(A0),-(SP) ;get the actual size.
|
||
MOVE.L D6,-(SP) ;compute floating extra times pointsize
|
||
_FixMul
|
||
MOVE.L (SP),D6 ;get fixed point answer
|
||
_FixRound ;round in case fractions are disabled
|
||
MOVE (SP)+,D0 ;pop the answer
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
|
||
TST.B FractEnable ;fractional widths? <06Nov85>
|
||
BNE.S MakeWTab ;yes, then don’t use the rounded result.
|
||
|
||
; Must overwrite default value of FoutExtra if FractEnable is not true but we are using fractional extra
|
||
; anyway—e.g. the FOND flags specify always use fractional widths. <PMAB559 BAL 9/7/88>
|
||
|
||
MOVE.B D0,FOutExtra ;and save the byte-sized result <PMAB569 BAL 9/7/88>
|
||
|
||
MakeITab
|
||
MOVEQ #0,D6 ;clear out D6
|
||
MOVE.B FOutExtra,D6 ;get extra value
|
||
EXT.W D6 ;sign extend it
|
||
SWAP D6 ;make it fixed point
|
||
MakeWTab
|
||
|
||
; the font changed so we have to make the table from scratch. First
|
||
; init the meta fields in the new table.
|
||
|
||
BSR DerefWidthTab ;get a pointer to the width table in A0
|
||
CMP #-1,widthFID(A0) ;is it a new one?
|
||
BNE AdjustSpace ;just take care of space extra
|
||
|
||
LEA WidthSExtra(A0),A1 ;point just past widths
|
||
CLR.L (A1)+ ;set lastSpExtra to 0
|
||
MOVE.L D6,(A1) ;set lastStyExtra to value
|
||
ADD.W #WidthAFID-WidthStyle,A1
|
||
MOVE.W FONDID,(A1)+
|
||
MOVE.L LastFOND,(A1)
|
||
|
||
; there are two cases for building the width table, depending on whether
|
||
; the font comes with a fixed-point table or not. Point A1 at either
|
||
; the offset/width table or the fixed-point width table
|
||
; better load it if it purged
|
||
|
||
MOVE.L FOutFontHandle,A0 ;get the current font handle, prepare for deref. later
|
||
BSR DeRefResource ;load resource who's handle is in A0.
|
||
|
||
; D2 holds the flags word, D3 has firstChar and D4 has lastChar. Compute
|
||
; the size of the tables in D5.
|
||
|
||
MOVEM.W (A0),D2-D4 ;get flags, first, last
|
||
MOVE D4,D5 ;copy lastChar
|
||
SUB.W D3,D5 ;compute lastChar-firstChar
|
||
MOVE D5,D1 ;keep # in D1
|
||
ADDQ #3,D5 ;# of chars, including missing
|
||
ADD.W D5,D5 ;compute size of table
|
||
EXT.L D5 ;make it a longWord
|
||
|
||
; compute address of offset/width table into A1
|
||
|
||
IF bugFix THEN
|
||
MOVE.W fNDescent(A0),D0 ;possibly the high word of owTLoc
|
||
SWAP D0 ;put it in the high word
|
||
BPL.S @notNegative
|
||
ENDIF
|
||
MOVEQ #0,D0
|
||
@notNegative
|
||
MOVE.W fOWTLoc(A0),D0 ;get size till owTable
|
||
ADD.L D0,D0 ;double for bytes
|
||
LEA fOWTLoc(A0,D0.L),A1
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; case out on the font format, pointing A1 at the right table and getting
|
||
; the width of the missing character in long format in D7
|
||
|
||
MOVEQ #0,D7 ;clear out D7
|
||
|
||
TST.B FractEnable ;use expanded widths?
|
||
BEQ.S @noExWidth ;if not, skip
|
||
|
||
BTST #1,D2 ;expanded width table present?
|
||
BNE.S @gotExWidth ;if so, skip
|
||
|
||
BTST #6,saveFondFlags ;set if FOND fractional widths are not (to be) used.
|
||
BNE.S @noExWidth ;if not, compute integral values from the font.
|
||
|
||
; See if we have a family width table for this font. A4 contains an offset to it if there is one
|
||
; (set up by MapFont) or is NIL.
|
||
|
||
MOVE.L A4,D0 ;got family width table?
|
||
BEQ.S @noExWidth ;if not, skip
|
||
|
||
; handle case of figuring out missing character width for family width table
|
||
|
||
MOVE.L LastFOND,A1 ;get famDef record
|
||
MOVE.L (A1),A1 ;handle -> pointer
|
||
ADD.L A4,A1 ;compute width tab ptr
|
||
BSR DerefWidthTab ;get pointer to width table in A0
|
||
MOVE.W WidthASize(A0),D0 ;get size in D0
|
||
MOVE.W -4(A1,D5),D7 ;get fixed point width
|
||
MULS D0,D7 ;scale it up
|
||
ASL.L #4,D7 ;convert to 32 bits <28Jun AJH>
|
||
BRA.S DoWTable ;back to common code
|
||
|
||
|
||
; this font doesn't have an expanded width table, so A1 is cool. Fetch
|
||
; the width of the missing character.
|
||
|
||
@noExWidth
|
||
MOVE.B -3(A1,D5),D7 ;get byte width
|
||
SWAP D7 ;convert to fixed point
|
||
BRA.S DoWTable ;go make the table
|
||
|
||
; the font does have an expanded width table, so adjust A1 and fetch the
|
||
; width of the missing character
|
||
|
||
@gotExWidth
|
||
ADD.L D5,A1 ;bump to expanded table
|
||
MOVE.W -4(A1,D5),D7 ;get fixed point width
|
||
ASL.L #8,D7 ;convert to 32 bits
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; build the width table
|
||
|
||
DoWTable
|
||
|
||
; set up D5 with a boolean that specifies whether we have to call FixMul
|
||
; to do the scale-disable scaling
|
||
|
||
CMP.L #$10000,FScaleHFact ;scale factor = 1
|
||
SNE D5 ;if = 1, make it 0 <10-30-85>
|
||
AND.B FScaleDisable,D5 ;FScaleDisable must be on, too
|
||
|
||
; OK, start making the width table by filling in the missing characters
|
||
; for "minChar" characters
|
||
|
||
MOVE.L D7,D0 ; <10-30-85>
|
||
BSR.S AddD6ScaleD0 ;add extra to missing width, scale by FScaleHFactor.
|
||
MOVE.L D0,D7 ; <10-30-85>
|
||
BSR DerefWidthTab ;get pointer to width table in A0
|
||
|
||
BRA.S @minCharSkip ;WHILE, not REPEAT
|
||
@minCharLoop
|
||
MOVE.L D7,(A0)+ ;stuff in missing width
|
||
@minCharSkip
|
||
DBRA D3,@minCharLoop ;repeat till done
|
||
|
||
; now we case out to two separate loops for filling out the body of the
|
||
; width table, depending on if we have an expanded table.
|
||
|
||
CLR.B UsedFWidths ;assume we don't use them
|
||
|
||
TST.B FractEnable ;fraction widths enabled?
|
||
BEQ.S CalcOldWLoop ;if not, skip
|
||
BTST #1,D2 ;which format? (check for width table in font)
|
||
BEQ.S CheckFracWidths ;if not expanded, see if there is a FOND.
|
||
|
||
@gotXWid1
|
||
MOVEQ #0,D0 ;clear out D0
|
||
MOVE.W (A1)+,D3 ;get 8.8 character width
|
||
|
||
CMP.W #-1,D3 ;is it missing?
|
||
BNE.S @notMissing ;if not, go handle
|
||
|
||
MOVE.L D7,D0 ;use missing width
|
||
BRA.S @stuffWidth ;go stuff it
|
||
@notMissing
|
||
MOVE.W D3,D0 ;get width
|
||
ASL.L #8,D0 ;make it 16.16 fixed-point
|
||
BSR.S AddD6ScaleD0 ;add extra, and scale if enabled
|
||
@stuffWidth ;
|
||
MOVE.L D0,(A0)+ ;stuff it
|
||
|
||
DBRA D1,@gotXWid1 ;loop for # of chars
|
||
|
||
ST UsedFWidths ;we used them
|
||
BRA.S FillTheRest
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; we might have a family width table -- if we do, use a different loop
|
||
CheckFracWidths
|
||
BTST #6,saveFondFlags ;set if no fractional family widths
|
||
BNE.S CalcOldWLoop ;if set, compute integral values from the font.
|
||
|
||
MOVE.L A4,D0 ;got a family one?
|
||
BEQ.S CalcOldWLoop ;if not, must be old way.
|
||
|
||
; use family widths to figure sizes
|
||
|
||
MOVE.L WidthTabHandle,A4
|
||
MOVE.L (A4),A4
|
||
MOVE.W WidthASize(A4),-(SP) ;get the actual size, keep on stack.
|
||
MOVE.L D0,A4 ;restore index to family widths
|
||
@fxWidLoop
|
||
MOVEQ #0,D0 ;clear out D0
|
||
MOVE.W (A1)+,D3 ;get 4.12 1-point width
|
||
|
||
CMP.W #-1,D3 ;is it missing?
|
||
BNE.S @0 ;if not, go handle
|
||
|
||
MOVE.L D7,D0 ;use missing width
|
||
BRA.S @1 ;go stuff it
|
||
@0
|
||
MOVE.W D3,D0 ;get width
|
||
MULU (SP),D0 ;scale it up
|
||
ASL.L #4,D0 ;adjust to 16.16 fixed point
|
||
BSR.S AddD6ScaleD0 ;add extra, and scale if enabled
|
||
@1 ; <10-30-85>
|
||
MOVE.L D0,(A0)+ ;stuff it
|
||
|
||
DBRA D1,@fxWidLoop ;loop for # of chars
|
||
|
||
ADDQ #2,SP ;pop off point size
|
||
ST UsedFWidths ;we used them
|
||
BRA.S FillTheRest
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; common utility routine
|
||
; AddD6ScaleD0 adds in the style extra in D6, then multiplies the value in D0 by the
|
||
; FScaleDisable scale factor.
|
||
|
||
AddD6ScaleD0
|
||
TST.L D0 ;is it zero?
|
||
BEQ.S @0 ;if it has no width, do nothing
|
||
ADD.L D6,D0 ;add in style extra first
|
||
TST.B D5 ; need to scale it?
|
||
BEQ.S @0
|
||
|
||
; *** note that the smaller ELSE case is OK, since changing FixMul’s register conventions breaks applications
|
||
|
||
IF 0 THEN
|
||
MOVEM.L A1/A0/D1,-(SP) ;save registers used by FixMul (D1, A0, A1)
|
||
SUBQ #4,SP ;make room for result
|
||
MOVE.L D0,-(SP) ;pass param D0
|
||
MOVE.L FScaleHFact,-(SP)
|
||
_FixMul ;
|
||
MOVEM.L (SP)+,D0-D1/A0-A1 ;function result (D0), restore registers (D1, A0, A1)
|
||
ELSE
|
||
MOVEM.L A1/A0/D1/D0,-(SP) ;save registers used by FixMul (A0, A1)
|
||
;make room for result (D1), pass param D0
|
||
MOVE.L FScaleHFact,-(SP)
|
||
_FixMul ;
|
||
MOVEM.L (SP)+,D0/A0-A1 ;function result (D0), restore registers (A0, A1)
|
||
ENDIF
|
||
@0
|
||
RTS
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
CalcOldWLoop
|
||
; its the old format, so walk down the o/w table, computing the fixed point
|
||
; widths and stuffing them into the table.
|
||
MOVEQ #0,D0 ;clear out D0
|
||
MOVE.W (A1)+,D3 ;get offset/width
|
||
CMP #-1,D3 ;is it missing?
|
||
BNE.S @skipMiss ;if non-missing, skip
|
||
|
||
MOVE.L D7,D0 ;use missing width
|
||
BRA.S @stuffIt ;go stuff it
|
||
@skipMiss
|
||
MOVE.B D3,D0 ;get width
|
||
SWAP D0 ;make it fixed-point
|
||
BSR.S AddD6ScaleD0 ; nop if not scale disabled
|
||
@stuffIt ;
|
||
MOVE.L D0,(A0)+ ;stuff it
|
||
|
||
DBRA D1,CalcOldWLoop ;loop for # of chars
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; OK, now fill out the end of the table with the missing character width
|
||
FillTheRest
|
||
MOVE #255,D0
|
||
SUB.W D4,D0 ;how many left?
|
||
BRA.S @whileStart ;let DBRA decrement first
|
||
@maxCharLoop
|
||
MOVE.L D7,(A0)+ ;stuff the width
|
||
@whileStart
|
||
DBRA D0,@maxCharLoop ;repeat till done
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; Short cut space extra check at the beginning of SwapFont jumps to here. Also, cached widths case jumps
|
||
; here.
|
||
|
||
AdjustSpace
|
||
BSR DerefWidthTab ;get pointer to width table in A0
|
||
LEA widthSExtra(A0),A1 ;figure where space is
|
||
|
||
; Believe it or not, it is possible that QuickDraw is not around at all, so test first.
|
||
|
||
MOVE.L (A1),D7
|
||
TST.B QDExist ;is QuickDraw around
|
||
BMI.S @noQuickDraw
|
||
MOVE.L grafGlobals(A5),A0 ;get grafGlobals
|
||
MOVE.L thePort(A0),D0 ;get thePort
|
||
BEQ.S @noQuickDraw
|
||
MOVE.L D0,A0
|
||
MOVE.L spExtra(A0),D7 ;get current space extra
|
||
@noQuickDraw
|
||
MOVE.L D7,LastSpExtra ;and remember it for next time.
|
||
|
||
SUB.L (A1),D7 ;subtract old with current
|
||
BEQ.S @checkDevice ;if same, nothing to do
|
||
|
||
; D7 has the difference in the value of spaceExtra. The only problem is spaceExtra is given in screen
|
||
; coordinates but we must return stuff in font coordinate space. Thus we must scale spaceExtra before
|
||
; adding it in. FMInNumer.h FOutDenom.h
|
||
; width = ———————— * ———————— * spExtra
|
||
; FMInDenom.h FOutNumer.h
|
||
|
||
ADD.L D7,(A1) ;remember new value
|
||
|
||
SUB.W #12,SP ;make space on stack
|
||
|
||
MOVE.W FMInNumer+2(A3),-(SP) ;push x input numer
|
||
MOVE.W FMInDenom+2(A3),-(SP) ;push x input denom
|
||
_FixRatio ;compute ratio
|
||
|
||
SUBQ #4,SP ;make space for result
|
||
MOVE.W FOutDenom+2,-(SP) ;push x output denom
|
||
MOVE.W FOutNumer+2,-(SP) ;push x output numer
|
||
_FixRatio ;compute ratio
|
||
_FixMul ;calculate scale factor
|
||
|
||
MOVE.L D7,-(SP) ;push space extra
|
||
_FixMul ;scale it
|
||
|
||
; we have the adjustment factor on the stack, so add it into the table
|
||
|
||
BSR DerefWidthTab ;get pointer to width table in A0
|
||
MOVE.L (SP)+,D0 ;get scaled delta
|
||
ADD.L D0,4*' '(A0) ;adjust space width
|
||
|
||
; Now that we finally have everything the way we want it, let the current
|
||
; device have a crack at changing things if it wants to.
|
||
|
||
@checkDevice
|
||
MOVEQ #-1,D0 ;get lots of ones
|
||
MOVE.B FMInDevice(A3),D0 ;get the device number
|
||
BEQ.S @doneStyle ;if its the screen, we're done
|
||
|
||
; call the driver to give it a chance to change the output record
|
||
|
||
LEA paramBlk(A6),A0 ;point A0 at OS block
|
||
MOVE.W D0,IORefNum(A0) ;set up the refNum
|
||
MOVE.W #FMgrCtl1,CSCode(A0) ;set up the control code
|
||
MOVE.L A3,CSParam(A0) ;pass the input record as a parameter
|
||
MOVE.W FMInDevice(A3),CSParam+4(A0) ;pass subclass, too
|
||
_Control
|
||
|
||
; All done now so copy the input record into the current record for the next time.
|
||
|
||
@doneStyle
|
||
MOVE.L 8(A6),A3 ;point to original input record
|
||
MOVE.L A3,A0
|
||
LEA CurFMInput,A1 ;point to current record
|
||
|
||
MOVE.L (A0)+,(A1)+ ;copy first 4 bytes
|
||
MOVE.L (A0)+,(A1)+ ;copy next 4 bytes
|
||
MOVE.L (A0)+,(A1)+ ;copy next 4 bytes
|
||
MOVE.L (A0)+,(A1)+ ;copy last 4 bytes
|
||
|
||
BSR DerefWidthTab ;get pointer to width table in A0
|
||
CMP #-1,widthFID(A0) ;already filled out? (cache case)
|
||
BNE.S @skipFill
|
||
|
||
MOVE.B UsedFWidths,WidthUsedFam(A0);update UsedFam.
|
||
MOVE.B FOutCurStyle,WidthAFace(A0) ;update Actual Face.
|
||
|
||
LEA widthFID(A0),A1 ;point to request info (Font ID etc) in width.
|
||
BSR FamSizeInD0
|
||
MOVE.L D0,(A1)+ ;update requested Font ID and Size.
|
||
ADDQ #4,A3
|
||
MOVE.L (A3)+,(A1)+ ;update requested face and device.
|
||
CLR.B -3(A1) ;but clear the needBits field
|
||
MOVE.L (A3)+,(A1)+ ;update numer, denom
|
||
MOVE.L (A3),(A1) ; of the scale factors.
|
||
@skipFill
|
||
MOVEM.L (SP)+,D3-D7/A2-A4 ;restore work registers.
|
||
MOVE saveMap(A6),D0 ;saved resource map or 0
|
||
BEQ.S @skipSave
|
||
MOVE D0,curMap
|
||
@skipSave
|
||
UNLK A6
|
||
BRA CheckPurged
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
; MapFont does all the hard work in FMSwapFont. Given a pointer to the
|
||
; font input record in A3, it normalizes the scale, finds the best set
|
||
; of bits it can and installs them into the output record.
|
||
;———————————————————————————————————————————————————————————————————
|
||
|
||
MapFont
|
||
SUB.L A4,A4 ;no family widths yet!
|
||
MOVE.W fmInSize(A3),D5 ;get the size in D5
|
||
MOVE.W fmInFamily(A3),D3 ;get the family
|
||
|
||
; OK, now D3 has the family we want. Now scale the size based on the current
|
||
; DotsPerInch and numer/denom and build the resource ID of the font we want
|
||
; (even though we might not have it)
|
||
|
||
CalcRealSize
|
||
SUB #14,SP ;make space for function results
|
||
MOVE.W FMDotsPerInch+2,-(SP) ;push horizontal dots/inch
|
||
MOVE.W #80,-(SP) ;push nominal dots/inch
|
||
_FixRatio ;turn into fixed point
|
||
|
||
SUBQ #4,SP ;make some room
|
||
MOVE.W fmInNumer+2(A3),-(SP) ;push horizontal numerator
|
||
MOVE.W fmInDenom+2(A3),-(SP) ;push horizontal denominator
|
||
_FixRatio ;make that a fixed point, too
|
||
_FixMul ;multiply them together.
|
||
|
||
CLR.W -(SP) ;fraction part is 0
|
||
MOVE.W D5,-(SP) ; push the size
|
||
_FixMul ;scale the size.
|
||
|
||
_FixRound ;round it off
|
||
|
||
; At this point the desired family is in D3 and the desired size is on the top of the stack. See if we have a
|
||
; family definition record for this family; if so, handle it the new way. Try to get a record of type
|
||
; <FOND,D3> into D0. Since this is sometimes speed critical, we implement a cache to skip the difficult
|
||
; resource search if we can. The FOND in the first element of the cache, WidthTabHandle, is always
|
||
; unpurgable.
|
||
|
||
TryForFond
|
||
CMP.W FondID,D3 ;same as last time
|
||
BEQ.S @sameFDef ;if so, short-circuit
|
||
|
||
MOVE.L LastFOND,A0 ;get old one (if zero, _HSetState will reject)
|
||
MOVE.B FondState,D0
|
||
_HSetState ;restore purge state
|
||
MOVE D3,D1
|
||
MOVE.W #MapTRUE,ROMMapInsert ;get from ROM if possible <10 Jul 85>
|
||
BSR GetFOND ;use common utility below (GetFontName)
|
||
BEQ.S @doneFDEFGet ;if no FOND, skip caching
|
||
|
||
; OK, we're changing the state of the cache so restore the purge state of
|
||
; the old one (if any), and make the new one unpurgable
|
||
|
||
MOVE.L (A0),A1 ;get a byte of FOND flag word and save it in low mem.
|
||
MOVE.B (A1),saveFondFlags ;bit 6 will be used to disable fractional junk.
|
||
|
||
_HGetState
|
||
MOVE.B D0,FondState ;save the old state
|
||
_HNoPurge ;make it non-purgable
|
||
@doneFDEFGet
|
||
|
||
; Check disk switch status here; better late than never…
|
||
|
||
CMP.B #-1,FontFlag
|
||
BEQ Pop6SubFont ;if so, go start over.
|
||
|
||
MOVE.W D3,FONDID ;moved these two lines from above <DLD,8-19-85>
|
||
MOVE.L A0,LastFOND ;so we will cache when no FOND. <DLD,8-19-85>
|
||
|
||
; the cache worked, so fetch it from low memory
|
||
|
||
@sameFDef
|
||
MOVE.L LastFOND,D0
|
||
BNE NewFontLookUp ;if so, go look up size
|
||
CMP #512,D3 ;if greater than 511, must have FOND
|
||
BLO.S OldFontLookUp ;if in old range, use old method
|
||
BRA Pop6SubFont ;if not, start up the great substitution engine
|
||
|
||
; utility subroutine to save code -- or in the size
|
||
|
||
OrInSize
|
||
AND #$FF80,D3 ;use high nine bits from that
|
||
OR D0,D3 ;combine family and size
|
||
BSR GetFontHandle ;got it? return to caller
|
||
BVS Pop8SubFont ;go start over if disk switch hook came up.
|
||
RTS
|
||
|
||
; after all that work, the desired size is on the top of the stack. Now we'll
|
||
; use it to build the resource ID of the desired font in D3
|
||
|
||
OldFontLookUp
|
||
MOVE.W (SP)+,D0 ;get the desired size
|
||
BNE.S @notZero ;this calculated if zero, should be made 1.
|
||
MOVEQ #1,D0
|
||
@notZero
|
||
AND #$007F,D0 ;use only low 7 bits
|
||
ASL #7,D3 ;make room for size field
|
||
OR D0,D3 ;add in the size bits
|
||
MOVE D0,D7 ;save target size
|
||
|
||
; At this point, D3 has the resource ID of the font we want. See if its there.
|
||
|
||
BSR GetFontHandle ;get the font, if we can
|
||
BVS Pop4SubFont ;;go start over if disk switch hook came up.
|
||
BNE.S GotTheFont ;if we got it, stop searching
|
||
|
||
; we couldn't find the one we wanted so try for 2X and .5X for the general
|
||
; search.
|
||
|
||
MOVE.W D3,D4 ;remember where we started
|
||
|
||
MOVE D7,D0 ;get target size
|
||
CMP #64,D0 ;is it > 64?
|
||
BGE.S SkipDouble ;if so, forget about doubling
|
||
|
||
ADD D0,D0 ;compute doubled size
|
||
BSR.S OrInSize ;or in the size
|
||
BNE.S GotTheFont ;if so, use it
|
||
|
||
; well, 2X didn't work so try .5X
|
||
|
||
SkipDouble
|
||
MOVE D7,D0 ;get target size
|
||
LSR #1,D0 ;divide by 2
|
||
BCS.S SkipHalf ;if odd, we're out of luck
|
||
|
||
BSR.S OrInSize ;or in the size
|
||
BNE.S GotTheFont ;if so, go use it
|
||
|
||
; we couldn't find a 2X or 1/2X match so start scanning up. If that doesn't
|
||
; work, scan down.
|
||
|
||
SkipHalf
|
||
MOVE D4,D3 ;retreive starting place
|
||
MOVEQ #1,D6 ;search up first
|
||
TST.B FScaleDisable ;scaling disabled?
|
||
BEQ.S scanFontLoop
|
||
MOVEQ #-1,D6 ;search down then
|
||
ScanFontLoop
|
||
ADD D6,D3 ;bump to the next size
|
||
AND #$007F,D3 ;only the low 7 bits are significant
|
||
BEQ ScanDone ;if we reach zero, done direction
|
||
|
||
MOVE D4,D0 ;get the original
|
||
AND #$FF80,D0 ;mask off size
|
||
OR D0,D3 ;build new one
|
||
|
||
; see if we have this one
|
||
|
||
BSR GetFontHandle ;get the font handle if we can
|
||
BVS Pop4SubFont ;go start over if disk switch hook came up.
|
||
BEQ.S ScanFontLoop ;if we couldn't, loop again
|
||
|
||
; we found a font so install it and compute the appropriate numer/denom
|
||
;
|
||
; Numer' := Numer * requested size * DotsPerInch
|
||
; -----------------------------------------------
|
||
; Denom' := Denom * actual size * 80
|
||
;
|
||
; Font handle in A0, size in D3.
|
||
GotTheFont
|
||
MOVE.L A0,FOutFontHandle ;install the font handle
|
||
BSR BuildCharTable ;make the character (height) table
|
||
|
||
SUBQ #4,SP ;make room for result
|
||
MOVE fmInSize(A3),-(SP) ;push desired size
|
||
MOVE D3,-(SP) ;push actual size
|
||
AND #$007F,(SP) ;use only low 7 bits
|
||
_FixRatio ;make it a fixed point number.
|
||
MOVE.L (SP)+,D6 ;keep size scale in D6
|
||
|
||
BSR DerefWidthTab ;get pointer to width table in A0
|
||
MOVE.W D3,WidthASize(A0) ;save actual size in width table.
|
||
MOVE.L FOutFontHandle,WidTabFont(A0)
|
||
|
||
MOVEQ #0,D5 ;first do the vertical
|
||
BSR.S MapScale ;calculate numer.v/denom.v
|
||
MOVEQ #2,D5 ;now do the horizontal
|
||
|
||
; compute the new numer/demon as a fixed point number, then rationalize it
|
||
; and stick it where it belongs
|
||
|
||
MapScale
|
||
SUB #12,SP ;make some space for results *** was 12 ***
|
||
MOVE.W fmInNumer(A3,D5),-(SP) ;push the numer
|
||
MOVE.W fmInDenom(A3,D5),-(SP) ;push the denom
|
||
_FixRatio ;compute the ratio.
|
||
|
||
SUBQ #4,SP ;make room for result
|
||
LEA FMDotsPerInch,A0 ;point to the dots/inch factor
|
||
MOVE.W 0(A0,D5),-(SP) ;push the dots/inch
|
||
MOVE.W #80,-(SP) ;the screen is 80 dots/inch
|
||
_FixRatio ;make it a rational number.
|
||
_FixMul ;multiply them together.
|
||
MOVE.L D6,-(SP) ;push the size scale
|
||
_FixMul ;multiply that in, too.
|
||
|
||
|
||
LEA FOutNumer,A0 ;point to the place to stuff result
|
||
MOVE.L (SP)+,D0 ;get the fixed point result
|
||
ADD.L #$80,D0 ;*** round it up
|
||
LSR.L #8,D0 ;take the middle 16 bits
|
||
|
||
MOVE.W D0,0(A0,D5) ;store the numerator
|
||
|
||
MOVE.W #256,4(A0,D5) ;the denom is 256
|
||
|
||
MOVE.L FPointOne,D1 ;set up FScaleHFact, FScaleVFact when disabled
|
||
TST.B FScaleDisable ;scaling disabled?
|
||
BEQ.S GoScaleLess ;if not, skip
|
||
|
||
MOVEQ #0,D1 ;zero top half of scale factor
|
||
MOVE.W D0,D1 ;remember it
|
||
MOVE #256,D0 ;start value for numerator
|
||
@2
|
||
CMP #512,D1 ; scale up > 2 x
|
||
BLO.S @4
|
||
|
||
ASL #1,D0 ; multiply numer by two
|
||
ASR #1,D1 ; divide scale factor by two
|
||
BRA.S @2
|
||
@4
|
||
CMP #192,D1 ; scale down < .75?
|
||
BHS.S @6
|
||
|
||
ASR #1,D0 ; multiply by 1/2
|
||
ASL #1,D1 ; divide by 1/2
|
||
BRA.S @4
|
||
@6
|
||
CMP #256,D1 ; scale down between 1x and 2x
|
||
BHS.S @doneScale
|
||
|
||
MOVE D0,D2 ; * 3
|
||
ADD D0,D0
|
||
ADD D2,D0
|
||
ASR #2,D0 ; multiply by 3/4ths
|
||
ASL #2,D1 ; divide by 3/4ths
|
||
DIVU #3,D1
|
||
EXT.L D1
|
||
@doneScale
|
||
MOVE.W D0,0(A0,D5) ;stuff numer
|
||
ASL.L #8,D1 ;fixate scale factor
|
||
|
||
; scaling is disabled so calculate the width factor adjustment
|
||
GoScaleLess
|
||
TST D5 ;horizontal?
|
||
BEQ.S @didVChange ;if not, skip
|
||
|
||
MOVE.L D1,FScaleHFact ;save new scale factor
|
||
BRA.S @scaleless
|
||
|
||
; compute vertical scaling factor too
|
||
|
||
@didVChange
|
||
MOVE.L D1,FScaleVFact ; record new V factor
|
||
@scaleless
|
||
MOVE.L WidthTabHandle,A1
|
||
MOVE.L (A1),A1 ;and remember it in the width table too.
|
||
LEA WidthVOutput(A1),A1
|
||
MOVE.W D0,0(A1,D5)
|
||
ASR.L #8,D1 ;shift scale factor back to a word.
|
||
MOVE.W D1,WidthVFactor-WidthVOutput(A1,D5)
|
||
|
||
RTS ;second time through, this ends MapFont
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
; At this point, we've scanned all we can in one direction. If scaling is not allowed, then we started
|
||
; scanning down so now we must scan up; the opposite is true if scaling is allowed. If we have scanned
|
||
; in both directions, then start up the great font substitution machine.
|
||
|
||
ScanDone
|
||
TST.B FScaleDisable ; scaling disabled?
|
||
BEQ.S @0
|
||
NEG D6 ;negate the direction
|
||
BMI.S Pop4SubFont ;if negative now, we must substitute
|
||
BRA.S @1 ; go on
|
||
@0
|
||
NEG D6 ;negate the direction
|
||
BPL.S Pop4SubFont ;if positive now, we must substitute
|
||
@1
|
||
MOVE D4,D3 ;start with the target again
|
||
BRA ScanFontLoop ;try our luck scanning down
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
;A word or two about font substitution:
|
||
;
|
||
; FontFlag is set to the current substitution level. If we get to SubFont, then the font requested is not
|
||
; available, or the disk switch hook drew in the system font while loading the requested FOND, FONT or
|
||
; NFNT. The value in FontFlag indicates what just happened, and what should be substituted next:
|
||
; -2 = The LoadResource failed at CheckPurged, although the font is the same one returned the last
|
||
; time SwapFont was called. (Maybe the user filled up memory, purging a large font.) Try for
|
||
; the same font again, so that a family-related substitute will be returned.
|
||
; -1 = The code was re-entered by the SysError (either a real problem or the disk switch hook.) The
|
||
; requested FOND, NFNT, or FONT may have been loaded, but the cache & low memory is no good.
|
||
; Try for the same font again.
|
||
; 0 = The requested font is not available, nor any reasonable family-related substitute. Try the
|
||
; ApFontID, if it is in the same neighborhood.
|
||
; 2 = The ApFontID family is not available. Try the base of the neighborhood.
|
||
; 4 = The base of the neighborhood is not available (Geneva, for the Roman neighborhood). Try the
|
||
; SysFontFam if it is in the same neighborhood.
|
||
; 6 = The SysFontFam family is not available. Try Font 0, setting curMap to the system map.
|
||
; 8 = (Disk switch only.) Give Chicago 12 a shot (same as 6).
|
||
|
||
|
||
; we have to substitute; use either the application or system font.
|
||
; Substitution order is:
|
||
; if the apFontID is in the same neighborhood as the requested font, use it.
|
||
; if not, or not available, use the base of the neighborhood (Geneva if the neighborhood is Roman.)
|
||
; if not available, use the sysFontFam, but only if it is in the same neighborhood as the request.
|
||
; if not, or not available, use the ROM font (hard coded to family 0, Chicago.)
|
||
|
||
Pop8SubFont
|
||
ADDQ #2,SP ;entry for throwing 2 return addresses away
|
||
Pop6SubFont
|
||
ADDQ #2,SP ;entry for throwing away scaled size, return address
|
||
Pop4SubFont
|
||
ADDQ #4,SP ;throw away return address for next time through
|
||
SubFont
|
||
; determine which to go to next
|
||
MOVE (A3),D3 ;set up font family
|
||
MOVEQ #0,D0
|
||
MOVE.B FontFlag,D0
|
||
BPL.S @noDiskSwitch
|
||
BSR InvalWidthTab ;otherwise, toss first cache entry
|
||
CLR.B FontFlag ;set up to 0 to start all over
|
||
BRA.S @skipDispatch
|
||
@noDiskSwitch
|
||
ADDQ.B #2,FontFlag
|
||
MOVE SubJump(D0),D0
|
||
JSR SubJump(D0)
|
||
@skipDispatch
|
||
MOVE.L 8(A6),A1 ;get pointer to original input record
|
||
MOVE D3,fmInFamily(A3) ;set up new substitute family
|
||
MOVE fmInSize(A1),fmInSize(A3) ;copy size since may have to map to system font.
|
||
BRA TryAgain
|
||
|
||
SubJump DC.W tryApFontID-SubJump ;0
|
||
DC.W tryNeighborhoodBase-SubJump ;2
|
||
DC.W trySysFontFam-SubJump ;4
|
||
DC.W tryChicago-SubJump ;6
|
||
DC.W tryChicago-SubJump ;8
|
||
|
||
; Use apFontID if it is in the same neighborhood.
|
||
tryApFontID
|
||
MOVE ApFontID,D1
|
||
checkNeighborhood ;common entry point for system family as well.
|
||
MOVEQ #9,D2 ;convenient constant
|
||
LSR D2,D1
|
||
SUB #31,D1
|
||
BPL.S @apForiegn
|
||
MOVEQ #0,D1
|
||
@apForiegn
|
||
MOVE D3,D0 ;copy family
|
||
LSR D2,D0 ;divide by 512 (unsigned)
|
||
SUB #31,D0 ;first $4000 is Roman, rest are neighborhoods
|
||
BPL.S @notRoman
|
||
MOVEQ #0,D0 ;Roman is 0, first neighborhood 1, etc.
|
||
@notRoman
|
||
CMP D0,D1 ;is apFontID in the same neighborhood as D3?
|
||
BNE.S Pop4SubFont ;if not, use next substitution method
|
||
MOVE ApFontID,D3
|
||
RTS
|
||
|
||
; Use the base of the neighborhood.
|
||
tryNeighborhoodBase
|
||
CMP #$4000,D3
|
||
BLO.S @mustBeRoman
|
||
AND #$FE00,D3 ;base is neighborhood & ~512
|
||
RTS
|
||
@mustBeRoman
|
||
MOVEQ #3,D3 ;hard code to Geneva
|
||
RTS
|
||
|
||
; Use the SysFontFam if it is in the same neighborhood.
|
||
trySysFontFam
|
||
MOVE SysFontFam,D1
|
||
BRA.S checkNeighborhood
|
||
|
||
; This entry point is called from the top of SwapFont if from within SysError we failed.
|
||
GoTryChicago
|
||
LINK A6,#stackFrame
|
||
MOVEM.L D3-D7/A2-A4,-(SP) ;save work registers
|
||
MOVE.L 8(A6),A3 ;get input pointer
|
||
BSR.S tryChicago
|
||
BRA MoreDifFont
|
||
|
||
; Use the ROM font.
|
||
; have to be very careful here that D3 is not later substituted
|
||
tryChicago
|
||
MOVE CurMap,saveMap(A6) ;save the current map
|
||
MOVE SysMap,CurMap ;hard code to the system map
|
||
MOVEQ #0,D3 ;hard code to Chicago
|
||
RTS
|
||
|
||
|
||
; ——————————————————————————————————————————————————————————————————
|
||
; SetNewDevice is called when we notice that the device has changed.
|
||
; If the device is 0 (the screen), fill out the info ourselves,
|
||
; otherwise make a status call to the driver to get it. Called only in DifFont after noting that the device
|
||
; has changed.
|
||
|
||
SetNewDevice
|
||
IF patch THEN
|
||
IF onMac THEN
|
||
JMP $40EE82
|
||
ELSEIF onMacPP THEN
|
||
JMP $419A9A ; *NB Patch* need addresses for both SE and Plus.
|
||
ENDIF
|
||
ELSE
|
||
TST D0 ;is it the screen?
|
||
BEQ.S SetScreenDevice ;if so, no need to call the driver
|
||
|
||
MOVEQ #-1,D0 ;get some ones
|
||
MOVE.B fmInDevice(A3),D0 ;build the refNum
|
||
|
||
MOVEQ #IOQElSize,D1 ;get size of pBlock
|
||
SUB.L D1,SP ;make space for control record
|
||
|
||
LEA IORefNum(SP),A0 ;point A0 at OS block
|
||
MOVE.W D0,(A0)+ ;set up the refNum
|
||
MOVE.W #FMgrCtl1,(A0)+ ;set up the control code
|
||
LEA FMDotsPerInch,A1 ;get place to stash info
|
||
MOVE.L A1,(A0)+ ;tell the driver about it
|
||
MOVE.W fmInDevice(A3),(A0)+ ;pass subclass, too
|
||
MOVE.L SP,A0 ;point A0 at pBlock
|
||
_Status ;ask the driver
|
||
|
||
ADD.L D1,SP ;pop off parameter block
|
||
RTS
|
||
ENDIF
|
||
|
||
; Set up parameters for the screen
|
||
|
||
SetScreenDevice
|
||
IF patch THEN
|
||
IF onMac THEN
|
||
JMP $40EEAC
|
||
ELSEIF onMacPP THEN
|
||
JMP $419AC4 ; *NB Patch* need addresses for both SE and Plus.
|
||
ENDIF
|
||
ELSE
|
||
LEA FMDotsPerInch,A1 ;get place to stash info
|
||
LEA ScreenStyleTab,A0 ;point to the info
|
||
MOVEQ #28,D0 ;28 bytes of info to move
|
||
_BlockMove ;move it in
|
||
RTS
|
||
ENDIF
|
||
|
||
; we found it, but better make sure we can load it
|
||
;——————————————————————————————————————————————————————————————————
|
||
;
|
||
; Four ways to get a font handle:
|
||
;
|
||
; GetStrike: returns handle to unloaded FONT to get resource attributes of ID passed in D1.
|
||
; GetFontHandle: returns handle to loaded FONT passed in D3.
|
||
; GoLoadStrike: returns handle to loaded FONT or NFNT inside FOND offset in A0.
|
||
; LoadNewStrike: returns handle to loaded FONT or NFNT passed in D0.
|
||
;
|
||
; All routines return the font handle in A0 and D0, with the Z-flag set to reflect if it is nil.
|
||
;——————————————————————————————————————————————————————————————————
|
||
GoLoadStrike
|
||
MOVE.L (A0),D0 ;get style/ID words from FOND
|
||
MOVE.L D0,styleID(A6) ;remember for later
|
||
LoadNewStrike
|
||
MOVE.W #MapTRUE,ROMMapInsert ;ResLoad True for GetResource <10 july 85>
|
||
LoadNoROM
|
||
MOVE D0,-(SP) ;preserve ID
|
||
|
||
SUBQ #4,SP
|
||
MOVE.L #'NFNT',-(SP) ;push NFNT
|
||
MOVE.W D0,-(SP)
|
||
_GetResource ;got it?
|
||
MOVE.L (SP)+,D0
|
||
BEQ.S fontOnlyLoad ;if not, look for FONT
|
||
ADDQ #2,SP ;don't need original ID
|
||
BRA.S weGotIt ;return z clear, handle in D0.
|
||
|
||
; we couldn't find the NFNT, so look for a FONT
|
||
; Change GetStrike to GetResource with loading off, in order to get handle, but to bypass doomed GetHandleSize. <PBM164>
|
||
GetStrike
|
||
MOVE.W #MapFALSE,ROMMapInsert ;don't load the font <10 July 85>
|
||
SUBQ #4,SP ;make space for function result <PBM164>
|
||
MOVE.L #'FONT',-(SP) ;'FONT' is resType
|
||
MOVE.W D1,-(SP) ;push ID
|
||
_GetResource
|
||
MOVE.L (SP)+,D0 ;get the love handle
|
||
BRA.S weGotIt ;use common code
|
||
GetFontHandle
|
||
MOVE D3,-(SP)
|
||
fontOnlyLoad
|
||
MOVE.W #MapTRUE,ROMMapInsert ;get FONT from ROM if possible <10july 85>
|
||
MOVE (SP)+,D0 ;recover ID
|
||
SUBQ #4,SP ;make space for function result
|
||
MOVE.L #'FONT',-(SP) ;'FONT' is resType
|
||
MOVE.W D0,-(SP) ;push ID
|
||
_GetResource
|
||
|
||
; But wait! What if we didn’t get a font at all? (Most probably because of some quirk of data in FOND, we just asked
|
||
; for and got the zero size FONT, which exists only in name.)
|
||
|
||
MOVE.L (SP)+,D0 ;sets Z flag
|
||
BEQ.S @weDidntGetIt ;if missing, skip checking size
|
||
MOVE.L D0,-(SP) ;protect handle from resource manager call
|
||
SUBQ #4,SP ;make room for function result
|
||
MOVE.L D0,-(SP)
|
||
_MaxSizeRsrc ;<1July87>
|
||
|
||
; A font with a single character has a $1A header, at least a 1 word strike, 2 word loc table, 2 entry o/w table, thus:
|
||
;
|
||
; Since Radius returns a 16 point system font which is not a resource, errors from MaxSizeRsrc
|
||
; are ignored.
|
||
|
||
CMP.L #$24,(SP)+ ;is it smaller than the minimal size
|
||
SLO D0 ;set D0 if it is too small to be useful
|
||
MOVE.L (SP)+,A0 ;restore handle to font
|
||
BRA.S setZBit
|
||
@weDidntGetIt
|
||
weGotIt
|
||
MOVE.L D0,A0 ;return it in A0
|
||
SEQ D0 ;save Z flag
|
||
setZBit
|
||
AND #4,D0 ;set only Z bit
|
||
CMP.B #-1,FontFlag ;was there a disk switch?
|
||
BNE.S @noDskSwitch ;if not, leave V flag clear
|
||
BSET #1,D0 ;set V bit
|
||
@noDskSwitch
|
||
MOVE D0,CCR ;return V set if switch, Z set if no resource
|
||
RTS
|
||
|
||
|
||
;——————————————————————————————————————————————————————————————————
|
||
; FindSize is a utility the scans the font family data structure for the
|
||
; size that's passed in D3. It uses the famDef handle in A2.
|
||
; >> rather than implied return for GoLoadStrike, may need to check FontFlag for -1.
|
||
;——————————————————————————————————————————————————————————————————
|
||
FindSize
|
||
MOVE.L (A2),A0 ;handle->pointer
|
||
LEA FONDAssoc(A0),A0 ;bump past header
|
||
MOVE.W (A0)+,D1 ;get the # of entries
|
||
@fSizeLoop
|
||
CMP.W (A0)+,D3 ;this the one?
|
||
BEQ.S GoLoadStrike ;if so, go load it (code above)
|
||
BLT.S @cantFind ;if too big, too late
|
||
|
||
ADDQ #FAssocSiz-2,A0 ;bump to next entry
|
||
DBRA D1,@fSizeLoop ;check them all out
|
||
@cantFind
|
||
MOVEQ #0,D0 ;z-flag set, return NIL
|
||
RTS
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————
|
||
; NewFontLookUp is passed the family definition record in D0 and the
|
||
; desired size on the top of the stack. It decides on the best strike
|
||
; to use, then uses common code to finish up.
|
||
;————————————————————————————————————————————————————————————————————
|
||
|
||
NewFontLookUp
|
||
MOVE.W (SP)+,D5 ;get desired size
|
||
MOVE.L D0,A2 ;keep fDef handle in A2
|
||
|
||
; first go for an exact match
|
||
|
||
MOVE D5,D3
|
||
BSR.S FindSize
|
||
BVS.S NewFailed
|
||
BNE.S GoFoundTheSize
|
||
|
||
; if FScaleDisable is on, don't bother to look for 2X and .5X first
|
||
|
||
TST.B FScaleDisable
|
||
BNE.S FindClosest
|
||
|
||
; now try for the one that's twice the size
|
||
|
||
ADD.W D3,D3
|
||
BSR.S FindSize
|
||
BVS.S NewFailed
|
||
BNE.S GoFoundTheSize
|
||
|
||
; try for the half-size one
|
||
|
||
MOVE D5,D3
|
||
LSR #1,D3
|
||
BCS.S FindClosest ;skip if the original size is odd.
|
||
BSR.S FindSize
|
||
BVS.S NewFailed
|
||
GoFoundTheSize
|
||
BNE.S FoundTheSize
|
||
|
||
; oh, well, beggars can't be choosers. Scan to find the closest one
|
||
; in size
|
||
|
||
FindClosest
|
||
MOVE.L (A2),A0 ;point to famDef
|
||
LEA FONDAssoc(A0),A0 ;point to size list
|
||
MOVE.W (A0)+,D4 ;get # of entries-1
|
||
MOVEQ #0,D1 ;no font yet
|
||
; << note the unnecessary limit of the 127 point size
|
||
; *** let’s try 32767 instead
|
||
MOVE #$7FFF,D2 ;closest delta so far
|
||
Scan4SizeLoop
|
||
MOVE.W D5,D0 ;get one we want <DLD-12-Sep-85>
|
||
SUB.W (A0),D0 ;compute delta
|
||
BPL.S @2
|
||
|
||
TST.B FScaleDisable ; scaling disabled?
|
||
BEQ.S @1 ; if so, see if we've got one lower
|
||
TST D1 ; if so, skip town
|
||
BNE.S sizeFound ; because we want to scale up
|
||
@1
|
||
NEG.W D0 ;absolute value
|
||
@2
|
||
CMP D2,D0 ;closest one yet
|
||
BGT.S NxtSizeLoop ;if not, skip
|
||
MOVE D0,D2 ;remember it
|
||
MOVE (A0),D1 ;remember font, too
|
||
NxtSizeLoop
|
||
ADDQ #FAssocSiz,A0 ;bump to next entry
|
||
DBRA D4,Scan4SizeLoop ;search them all
|
||
sizeFound
|
||
MOVE D1,D3 ;get best alternative
|
||
BSR.S FindSize ;try to get it...
|
||
BVS.S NewFailed
|
||
BEQ.S NewFailed ;if can’t get it, skip
|
||
|
||
; OK, we found the size so now worry about the style. The Font handle is
|
||
; in D0.
|
||
|
||
FoundTheSize
|
||
MOVE.L A0,D0 ;save the font handle in D0
|
||
MOVE.L (A2),A0 ;handle->pointer
|
||
LEA FONDAssoc(A0),A0 ;skip header
|
||
MOVE.W (A0)+,D1 ;fetch # of entries
|
||
FTSLoop
|
||
CMP.W (A0),D3 ;search for matching size
|
||
BEQ.S GotEntry
|
||
ADDQ #FAssocSiz,A0
|
||
DBRA D1,FTSLoop
|
||
;when could this ever fall through?
|
||
|
||
NewFailed ;we can't find any in the family FOND record so try the old way
|
||
MOVE D5,-(SP) ;put size on stack
|
||
MOVE (A3),D3 ;get the requested family
|
||
BRA OldFontLookUp
|
||
|
||
; Modification history:
|
||
; 13-Aug-86 CRC Fixed bugs with uninitialized FOND entry pointer, looking at data past end of FOND.
|
||
;
|
||
|
||
; Registers used:
|
||
; D0 = handle to font (input) D1 = left in assoc. table (input) D2 = user style descriptor, scratch
|
||
; D3 = actual size (input) D4 = best style weight, temp. D5 = scratch
|
||
; D6 = FOND style descriptor D7 = scratch A0 = FOND data pointer (input)
|
||
; A1 = best style entry A2 = handle to FOND A3 = input record
|
||
; A4 = offset to width table in FOND
|
||
;
|
||
; A0 points to the first entry of this size in the FOND, but maybe the FOND contains a stylized font that
|
||
; is better. Loop through to pick up the best qualifying one. The first font in the actual
|
||
; size pointed to by the FOND has already been successfully loaded, and is pointed to by D0.
|
||
|
||
; Both this routine and the earlier call to FindSize only make one call to GetResource; if that call fails,
|
||
; then other styles in the same size are not tried before going on to other methods of font substitution.
|
||
; A major reorganization of the code should include a thorough family search, retrying after failure until
|
||
; the family has been exhausted.
|
||
|
||
; >>> Styleweights needs to be driver supplied, at least for alternate display devices?
|
||
; StyleWeights is a table of weights for the font style bits, to determine which strike to display on
|
||
; the screen. Styles not provided by the strike returned are generated by QuickDraw.
|
||
|
||
StyleWeights
|
||
DC.B 4 ;weight for bold
|
||
DC.B 8 ;weight for italic
|
||
DC.B 1 ;weight for underline
|
||
DC.B 3 ;weight for outline
|
||
DC.B 3 ;weight for shadow
|
||
DC.B 2 ;weight for condensed
|
||
DC.B 1 ;weight for extended
|
||
DC.B 0 ;bit 7 unused
|
||
|
||
|
||
GotEntry
|
||
MOVEQ #0,D2 ;zero high byte of style
|
||
ADDQ #2,A0 ;point to style field
|
||
MOVEQ #-2,D4 ;init best metric
|
||
MOVE.B fmInFace(A3),D2 ;get style we want
|
||
@selectStyleLoop
|
||
MOVE.W (A0),D6 ;get style descriptor (want low byte only)
|
||
CMP D6,D2 ;do they match?
|
||
BNE.S @noStyleMatch
|
||
MOVE.L A0,A1 ;if so, we've got it!
|
||
BRA.S @foundMatch0
|
||
@noStyleMatch
|
||
MOVEQ #-1,D5 ;take the first entry for starters
|
||
MOVE D2,D7
|
||
NOT D7
|
||
AND D6,D7 ;can we use it?
|
||
BNE.S @nextStyle ;if not, skip
|
||
|
||
; it qualifies, so determine its weighting
|
||
|
||
MOVEQ #0,D5 ;initial weight is 0
|
||
MOVEQ #7,D7 ;start with bit 8
|
||
AND D2,D6 ;only bits set in both request & available
|
||
@styMagLoop
|
||
ASL.B #1,D6 ;bit set?
|
||
BCC.S @nextStyMag ;if not, skip
|
||
ADD.B StyleWeights(D7),D5 ;add in weight
|
||
@nextStyMag
|
||
DBRA D7,@styMagLoop ;loop for 8 bits
|
||
|
||
; OK, now see if the resulting weight (in D1) is the biggest so far
|
||
|
||
@nextStyle
|
||
CMP D5,D4 ;best so far?
|
||
BGE.S @loopBottom ;if not, forget it!
|
||
|
||
; its the biggest so far, so remember it
|
||
|
||
MOVE D5,D4 ;remember metric value
|
||
MOVE.L A0,A1 ;remember entry
|
||
|
||
; if we have more to consider, go handle them
|
||
|
||
@loopBottom
|
||
|
||
ADDQ #FAssocSiz-2,A0 ;bump to next entry
|
||
CMP.W (A0)+,D3 ;next one same size?
|
||
DBNE D1,@selectStyleLoop ;if not, or if out of entries, decide the style
|
||
|
||
; no more of this size so the winner is the one pointed to by A1. If the
|
||
; ID is the same as the one we already got, we don't have to get it
|
||
; again
|
||
|
||
@foundMatch0
|
||
MOVE.W (A1)+,D6 ;get the style of winner
|
||
MOVE.W styleID+2(A6),D1 ;get resID of one in D0
|
||
CMP.W (A1),D1 ;do we already have it?
|
||
MOVE.L D0,A0 ;keep fontHandle from now on in addr. reg.
|
||
BEQ.S @foundItAll ;if so, don't have to load
|
||
|
||
; it changed, so we have to get it again
|
||
|
||
MOVE.L A0,D4 ;remember old fonHandle
|
||
|
||
MOVE.W (A1),D0 ;get ID
|
||
BSR LoadNewStrike ; << this is the only call to this subroutine,
|
||
; << but it is inside goLoadStrike (which is
|
||
; << also called only once.)
|
||
; << uses only A0, D0
|
||
BVS.S NewFailed ;disk switch, oh no.
|
||
BNE.S @foundItAll
|
||
|
||
@noTweakedFont
|
||
; we couldn't load it, so stick with the old one
|
||
|
||
MOVE.L D4,A0 ;recover fontHandle
|
||
MOVE.W styleID(A6),D6 ;recover style
|
||
|
||
; OK, the fontHandle is in D0 and its style is in D6. Set up FOutCurStyle
|
||
; with the proper value, and dive back in to the font manager proper.
|
||
|
||
@foundItAll
|
||
NOT D6 ;invert mask of what we got
|
||
AND.B D6,FOutCurStyle ;turn off built-in properties
|
||
|
||
; at this point D6 has the inverse of the style we actually got. A2 has
|
||
; the family definition record handle. Look for a matching width table;
|
||
; if we got one, return its offset in A4.
|
||
|
||
MOVE.L (A2),A1 ;point to famDef
|
||
|
||
MOVE.W FONDLast(A1),D1 ;get lastChar
|
||
BEQ.S @noFamWidths ;if zero, must be a “null” FOND set up by Font/DA Mover
|
||
|
||
SUB.W FONDFirst(A1),D1 ;compute # of chars-1
|
||
ADDQ #4,D1 ;compute word size of wTab (include style wd.)
|
||
ADD.W D1,D1 ;compute size of table
|
||
|
||
MOVE.L FONDWTabOff(A1),D0 ;get offset to widthTabs
|
||
BEQ.S @noFamWidths ;if none, skip
|
||
|
||
ADD.L D0,A1 ;point to the width tables
|
||
MOVE.W (A1)+,D2 ;get # of tables-1
|
||
BMI.S @noFamWidths ;skip if none
|
||
|
||
; here's the loop where we search for the appropriate family width table
|
||
; >> Adobe pointed out a bug here. If the FOND has a style width table, but the style screen font is not
|
||
; >> around, the plain width table will be used incorrectly. The right solution is for the styles to be
|
||
; >> searched and compared on a weighted basis just like the screen styles, except for the weights are
|
||
; >> different. Bold first, Condensed next, and Italic third? What about the idea of masking out
|
||
; >> underline, outline, shadow, and always forcing stylistic extras to be used, unless an exact match
|
||
; >> is found?
|
||
; >> Certainly, if a style width has styles outside of the requested style, it can not be used.
|
||
|
||
; >> Although this code is very similar to the screen font code above, I can’t see any trival way of
|
||
; >> rolling them together. For one, all registers are used.
|
||
|
||
;———————————————————————————————————————————————————————————————
|
||
; bug fix, implemented as a patch on Aladdin - the problem is that FOND widths will only be used
|
||
; if FractEnable is true; otherwise, the widths will be gotten from the strike.
|
||
; probably can skip this whole mess if FractEnable is false ---
|
||
IF bugFix THEN
|
||
@srchFamWTab
|
||
MOVEQ #-1,D4 ;best match found so far
|
||
TST.B FractEnable ;are fractions allowed?
|
||
BNE.S @useBestStyle ;if so, use the best width table around
|
||
NOT D6 ;reverse strike style once more
|
||
MOVE D6,-(SP) ;use width table equivalent to strike
|
||
BRA.S @nextFamWTab
|
||
@useBestStyle
|
||
MOVEQ #0,D0 ;zero high word
|
||
MOVE.B fmInFace(A3),D0 ;get original requested style
|
||
MOVE D0,-(SP) ;push it
|
||
@nextFamWTab
|
||
MOVE (SP),D0 ;get the style word
|
||
ELSE
|
||
@srchFamWTab
|
||
MOVEQ #-1,D4 ;best match found so far
|
||
MOVEQ #0,D0 ;zero high byte of style
|
||
@nextFamWTab
|
||
MOVE.B fmInFace(A3),D0 ;get original requested style
|
||
ENDIF
|
||
;———————————————————————————————————————————————————————————————
|
||
CMP (A1),D0 ;exact match?
|
||
BEQ.S @figureWidthPos ;don’t worry no more
|
||
NOT D0 ;set all cleared bits
|
||
AND (A1),D0 ;nonzero if style in width is not in request
|
||
BNE.S @wrongFamWidths ;don’t consider widths with too much info.
|
||
MOVEQ #0,D5 ;accumulated weight
|
||
;———————————————————————————————————————————————————————————————
|
||
; more of the same bug fix
|
||
IF bugFix THEN
|
||
MOVE (SP),D0
|
||
ELSE
|
||
MOVE.B fmInFace(A3),D0 ;bits in requested style
|
||
ENDIF
|
||
;———————————————————————————————————————————————————————————————
|
||
AND (A1),D0 ;and in available bits
|
||
MOVEQ #7,D7 ;number of bits in style byte
|
||
@nextBit
|
||
ASL.B #1,D0 ;
|
||
BCC.S @skipWeight ;
|
||
ADD.B widthWeights(D7),D5
|
||
@skipWeight
|
||
DBRA D7,@nextBit ;if no carry and not zero, go to next bit
|
||
CMP D5,D4
|
||
BGE.S @wrongFamWidths
|
||
MOVE D5,D4 ;save best
|
||
MOVE.L A1,D6 ;location of best width found so far
|
||
@wrongFamWidths
|
||
ADD D1,A1 ;advance to next table entry
|
||
DBRA D2,@nextFamWTab
|
||
TST D4
|
||
BMI.S @tossStackSpace ;<1July87>
|
||
MOVE.L D6,A1
|
||
@figureWidthPos
|
||
MOVE (A1)+,fwidStyle(A6) ;keep best found style
|
||
SUB.L (A2),A1
|
||
MOVE.L A1,A4
|
||
@tossStackSpace
|
||
IF bugFix THEN
|
||
ADDQ #2,SP
|
||
ENDIF
|
||
@noFamWidths
|
||
BRA GotTheFont ;dive back in
|
||
|
||
; output registers: (double dashes indicate registers are written before read)
|
||
; D0 = -- D1 = -- D2 = --
|
||
; D3 = actual size (input) D4 = -- D5 = --
|
||
; D6 = -- D7 = -- A0 = handle to font (input)
|
||
; A1 = -- A2 = -- A3 = input record
|
||
; A4 = offset to width table in FOND
|
||
|
||
; end of GotEntry
|
||
|
||
; WidthWeights are used to determine which width table in the FOND is the best approximation of the
|
||
; requested style widths. Styles not provided by the FOND width table are added in from the FOND values
|
||
; in style extra.
|
||
|
||
WidthWeights
|
||
DC.B 1 ;weight for bold
|
||
DC.B 3 ;weight for italic
|
||
DC.B 5 ;weight for underline
|
||
DC.B 4 ;weight for outline
|
||
DC.B 4 ;weight for shadow
|
||
DC.B 2 ;weight for condensed
|
||
DC.B 2 ;weight for extended
|
||
DC.B 0 ;bit 7 unused
|
||
|
||
|
||
FPointOne DC.W 1
|
||
DC.W 0
|
||
|
||
|
||
; PROCEDURE GetFontName(familyID: INTEGER; VAR theName: Str255);
|
||
;
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (GetFontName) (GetFontName)
|
||
;
|
||
; Get the name of the font, given the family ID
|
||
|
||
GetFontName
|
||
|
||
; first check if we have a family definition record
|
||
MOVE.L (SP)+,A1 ;save return address
|
||
MOVE.L (SP)+,D2 ;save pointer to string
|
||
MOVE.W (SP)+,D1 ;get the requested family ID
|
||
MOVE.W #MapFALSE,ROMMapInsert ;set ResLoading False <10 Jul 85>
|
||
BSR.S GetFONDMap ;is there a FOND for this family?
|
||
BNE.S @askForName ;if so, skip
|
||
|
||
; make sure the ID is in range
|
||
|
||
CMP.W #512,D1 ;ID in range?
|
||
BCC.S @returnNilString ;if not, skip
|
||
|
||
; no luck, so try it the old way
|
||
|
||
ASL #7,D1 ;set size field to 0
|
||
BSR GetStrike ;get the fontHandle
|
||
BEQ.S @returnNilString ;if NIL, return empty string
|
||
@askForName
|
||
MOVE.L A0,-(SP) ;push the resource handle
|
||
CLR.L -(SP) ;no place for ID (don't care)
|
||
CLR.L -(SP) ;no place for type (don't care)
|
||
MOVE.L D2,-(SP) ;place for name (where app wants)
|
||
MOVE.W #MapFALSE,ROMMapInsert ;get from ROM if possible <10 Jul 85>
|
||
_GetResInfo ;get it!
|
||
BRA.S @doneGetFName ;all done
|
||
|
||
@returnNilString
|
||
MOVE.L D2,A0 ;get the string pointer
|
||
CLR.B (A0) ;make it NIL
|
||
|
||
@doneGetFName
|
||
JMP (A1) ;return to caller
|
||
|
||
|
||
; Common code used by GetFontName and RealFont. GetFOND entry point is used by TryFOND.
|
||
;
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (GetFONDMap) (GetFONDMap)
|
||
;
|
||
; Need to map D1 into proper ID if 0 or 1
|
||
|
||
GetFONDMap
|
||
TST D1
|
||
BNE.S @notSysFont
|
||
MOVE SysFontFam,D1
|
||
BRA.S GetFOND
|
||
@notSysFont
|
||
CMP #1,D1 ;is it the same as the apFontID?
|
||
BNE.S GetFOND
|
||
MOVE ApFontID,D1
|
||
GetFOND
|
||
SUBQ #4,SP
|
||
MOVE.L #'FOND',-(SP) ;push type "FOND"
|
||
MOVE.W D1,-(SP) ;push the ID
|
||
_GetResource ;look for it
|
||
MOVE.L (SP)+,D0
|
||
MOVE.L D0,A0
|
||
RTS
|
||
|
||
|
||
; FUNCTION RealFont(famID: INTEGER; size: INTEGER): BOOLEAN;
|
||
;
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (RealFont) (RealFont)
|
||
;
|
||
; RealFont is a boolean function that returns true if we have a real bitmap
|
||
; (as opposed to a stretched one) for the requested font
|
||
;
|
||
; Modification History:
|
||
;
|
||
; 26-Aug-86 CRC Use same substitution scheme as SwapFont. Do not play with cache state
|
||
; anymore.
|
||
|
||
RealFont
|
||
MOVE.L (SP)+,A1 ;save return address
|
||
MOVE.W (SP)+,D2 ;get size
|
||
BNE.S @notSizeZero ;if nonzero, no prob with Bob
|
||
TST (SP) ;sysFontFam?
|
||
BNE.S @notSysFont ;if not, use FMDefaultSize
|
||
MOVE SysFontSize,D2 ;must be 0,0
|
||
BNE.S @notSizeZero ;if non zero, it is fine
|
||
@notSysFont
|
||
MOVEQ #0,D2 ;zero high order byte
|
||
MOVE.B FMDefaultSize,D2 ;pick up preset default
|
||
BNE.S @notSizeZero ;take it as long as it is not zero.
|
||
MOVEQ #12,D2 ;hardcode to 12 if low memory is no help
|
||
@notSizeZero
|
||
MOVE.W (SP)+,D1 ;get the font family
|
||
CLR.W (SP) ;assume we don't have it (set result false)
|
||
MOVE.W #MapTRUE,ROMMapInsert ;set ResLoading True
|
||
BSR.S GetFONDMap ;is there a FOND for this family?
|
||
BEQ.S @oldKindOfFont ;if not, try for old
|
||
|
||
; we have a family definition record (handle in D0), so scan it to see
|
||
; if the record contains an entry for that size
|
||
|
||
MOVE.L (A0),A0 ;handle->pointer
|
||
LEA FONDAssoc(A0),A0 ;skip header
|
||
MOVE.W (A0)+,D0 ;pick up the count
|
||
BMI.S @notReal ;if none, skip
|
||
|
||
@nrfLoop
|
||
CMP.W (A0),D2 ;got it?
|
||
BEQ.S @itsReal ;if so, its real
|
||
BLT.S @notReal ;if past it we're done
|
||
ADDQ #FAssocSiz,A0 ;skip to next entry
|
||
DBRA D0,@nrfLoop ;check em all out
|
||
|
||
BRA.S @notReal ;it must not be real...
|
||
|
||
@oldKindOfFont
|
||
; make sure the ID is in range for an old-style font
|
||
|
||
CMP.W #512,D1 ;ID in range?
|
||
BCC.S @notReal ;if not, return false
|
||
|
||
; there's no family definition record so do it the old way
|
||
|
||
ASL #7,D1 ;shift FamID into place
|
||
AND.W #$007F,D2 ;only use low 7 bits of size
|
||
OR D2,D1 ;compute resource ID
|
||
|
||
BSR GetStrike ;do we have it
|
||
BEQ.S @notReal ;good! (branch if we couldn't find it)
|
||
@itsReal
|
||
ADDQ.B #1,(SP) ;return TRUE
|
||
@notReal
|
||
JMP (A1) ;return to caller
|
||
|
||
|
||
; PROCEDURE SetFontLock(lockFlag:Boolean) -- makes the current font purgable
|
||
; or unpurgable.
|
||
|
||
SetFontLock
|
||
MOVE.L FOutFontHandle,A0 ;get the font handle
|
||
MOVE.L (SP)+,A1 ;get return address
|
||
TST.B (SP)+ ;set or clear lock?
|
||
BEQ.S @unlockFont ;if set, go lock it down
|
||
|
||
; we want to lock the font down so make sure its loaded and make it unpurgable
|
||
|
||
MOVE.L A0,-(SP) ;push font handle for release/load
|
||
MOVE.W #MapTrue,ROMMapInsert ;get it from ROM if possible <10 Jul 85>
|
||
_LoadResource ;load it in
|
||
_HNoPurge ;turn off purge bit
|
||
BCLR #purge,FondState
|
||
BRA.S @doneSFL
|
||
|
||
; we no longer need the font so make it purgable
|
||
|
||
@unlockFont
|
||
_HPurge ;make it purgable
|
||
BSET #purge,FondState
|
||
@doneSFL
|
||
JMP (A1) ;return to caller
|
||
|
||
|
||
; PROCEDURE SetFScaleDisable(scaleDis:BOOLEAN);
|
||
;
|
||
; Set to turn ScaleDisable on and off, invalidating the width cache.
|
||
|
||
SetFScaleDisable
|
||
MOVE.L (SP)+,A0
|
||
MOVE.B (SP)+,FScaleDisable
|
||
setFScaleTail
|
||
MOVE.L MinusOne,LastSpExtra ;note that widths are invalid
|
||
JMP (A0)
|
||
|
||
|
||
; PROCEDURE SetFractEnable(fractEnable:BOOLEAN);
|
||
;
|
||
; Set to turn FractEnable on and off, invalidating the width cache.
|
||
|
||
SetFractEnable
|
||
MOVE.L (SP)+,A0 ;return address
|
||
MOVE.B (SP)+,FractEnable
|
||
BRA.S setFScaleTail
|
||
|
||
|
||
; PROCEDURE FontMetrics(VAR theMetrics:FontMetricRec);
|
||
;
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (FontMetrics) (FontMetrics)
|
||
;
|
||
; FontMetrics returns fractional information about the current font
|
||
; as specified in thePort. It returns a Font Metric Record whose format
|
||
; is:
|
||
;
|
||
; ascent: Fixed;
|
||
; descent: Fixed;
|
||
; leading: Fixed;
|
||
; widMax: Fixed;
|
||
; WTabHandle: Handle;
|
||
;
|
||
|
||
; first use CharWidth to force a SwapFont
|
||
|
||
FontMetrics
|
||
SUBQ #2,SP ;make room for result
|
||
MOVE #' ',-(SP) ;push ASCII for blank
|
||
_CharWidth ;run through SwapFont
|
||
ADDQ #2,SP ;we don't really care about result
|
||
|
||
; get the parameter pointer
|
||
|
||
MOVE.L A2,-(SP) ;save work register
|
||
MOVE.L 8(SP),A2 ;point to result record
|
||
|
||
; always derive things from the font itself
|
||
|
||
MOVE.L FOutFontHandle,A1 ;get font handle
|
||
MOVE.L (A1),A1 ;handle->pointer
|
||
LEA FAscent(A1),A0 ;point to ascent field
|
||
PEA FWidMax(A1) ;save pointer to FWidMax for later
|
||
BSR.S ScaleVFVal ;process ascent
|
||
BSR.S ScaleVFVal ;process descent
|
||
BSR.S ScaleVFVal ;process leading
|
||
MOVE.L (SP)+,A0
|
||
MOVE.L FScaleHFact,D1
|
||
LEA fmOutNumer+FOutRec+2,A1 ;point to horizontal numerator.
|
||
BSR.S ScaleFVal ;process widMax
|
||
|
||
; stuff the width table handle
|
||
|
||
MOVE.L WidthTabHandle,A0
|
||
MOVE.L A0,(A2) ;remember width handle
|
||
|
||
; now adjust the results to compensate for style
|
||
|
||
MOVE.L 8(SP),A2 ;get result pointer back.
|
||
MOVEQ #0,D0
|
||
MOVE.B fmOutShadow+FOutRec,D0 ;get shadow count
|
||
BEQ.S @noShadow ;skip if zero
|
||
ADD.W #1,(A2) ;adjust ascent
|
||
ADD.W D0,4(A2) ;adjust descent
|
||
@noShadow
|
||
MOVE.L (A0),A0 ;pointer to widths
|
||
MOVE.L WidthStyle(A0),D0 ;get the style extra.
|
||
ADD.L D0,12(A2) ;add it in to the WidMax field.
|
||
|
||
; now we're done
|
||
|
||
MOVE.L (SP)+,A2 ;restore work register
|
||
MOVE.L (SP)+,(SP) ;strip parameter
|
||
RTS
|
||
|
||
|
||
; ScaleFVal is a code saving utility that fetches the value pointed
|
||
; to by A0, multiplies it by the scale factor and scale disable adjustment,
|
||
; and stuffs the normalized long result where A2 points
|
||
|
||
ScaleVFVal
|
||
MOVE.L FScaleVFact,D1
|
||
LEA fmOutNumer+FOutRec,A1 ;point to vertical numerator.
|
||
ScaleFVal
|
||
MOVE.W (A0)+,D0 ;get ascent
|
||
MOVE.L A0,-(SP)
|
||
TST.B FScaleDisable ;use 1.0 if scaling is enabled.
|
||
BNE.S @2
|
||
MOVE.L FPointOne,D1
|
||
@2
|
||
SUBQ #4,SP ;make space for result
|
||
MOVE.L D1,-(SP) ;FScale adjustment for FixMul
|
||
|
||
SUBQ #4,SP
|
||
CLR.W -(SP) ;push the font's info as a fixed point value.
|
||
MOVE.W D0,-(SP)
|
||
|
||
SUBQ #4,SP
|
||
; reversed next 2 lines <28May86>
|
||
MOVE.W (A1),-(SP) ;push V output numer
|
||
MOVE.W 4(A1),-(SP) ;push V output denom
|
||
_FixRatio ;compute ratio.
|
||
|
||
; multiply by the appropriate FScaleDisable factor in D1
|
||
|
||
_FixMul ;compute FScaleExtra*Value
|
||
_FixMul ;compute FScaleExtra*Value*ScaleFactor
|
||
MOVE.L (SP)+,(A2)+ ;remember it
|
||
MOVE.L (SP)+,A0
|
||
RTS
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————
|
||
; BuildCharTable operates on the font passed in A0. It makes room for
|
||
; a character height table at the end of the font and then loops from
|
||
; FirstChar to LastChar+1, computing it.
|
||
;
|
||
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
||
;AppleSystemPatch FontMgrPatch.a 01Jan1904 #??? (BuildCharTable) (BuildCharTable)
|
||
;
|
||
; Registers used:
|
||
;
|
||
; D0 = scratch D1 = scratch D2 = scratch D3 = character height
|
||
; D4 = constant (16) D5 = table size D6 = next entry, width D7 = locTable entry
|
||
; A0 = fontHandle (input) A1 = strike pointer A2 = fontPtr, locTable A3 = fontHandle
|
||
; A4 = character height A5 = mask table
|
||
|
||
RightMask EQU $0 ;position of right masks in QuickDraw’s table.
|
||
LeftMask EQU $20 ;position of left masks in QuickDraw’s table.
|
||
|
||
|
||
BuildCharTable
|
||
MOVEM.L D3-D7/A2-A5,-(SP) ;save registers
|
||
|
||
MOVE.L A0,A3 ;keep fontHandle in A3
|
||
_GetMaskTable
|
||
MOVE.L A0,A5 ;keep pointer to left masks around
|
||
MOVE.L (A3),A1 ;point to the font
|
||
MOVE.W (A1)+,D0 ;get format word?
|
||
LSR #1,D0 ;already got table?
|
||
BCS.S DoneBCT ;if so, we're done
|
||
|
||
; get firstChar, lastChar and compute size of table
|
||
|
||
MOVE.W (A1)+,D0 ;get firstChar
|
||
MOVEQ #0,D5 ;zero high word
|
||
MOVE.W (A1),D5 ;get lastChar
|
||
SUB.W D0,D5 ;compute lastChar-firstChar
|
||
ADDQ #3,D5 ;# of chars, including missing
|
||
ADD.W D5,D5 ;compute size of table
|
||
|
||
; compute total new size of font: position of OWTable + 2 * D5
|
||
|
||
MOVE.L (A3),A1 ;point to font
|
||
MOVEQ #0,D0
|
||
IF bugFix THEN
|
||
MOVE.W fNDescent(A1),D0 ;possibly the high word of owTLoc
|
||
BLE.S @negative
|
||
SWAP D0 ;put it in the high word
|
||
ENDIF
|
||
@negative
|
||
MOVE.W fOWTLoc(A1),D0 ;get size till owTable
|
||
ADDQ.L #8,D0 ;8 header words in front
|
||
ADD.L D0,D0 ;double for bytes
|
||
MOVE.L D0,D1 ;remember in D1
|
||
SUB.L D5,D1 ;compute offset to LocTable
|
||
ADD.L D5,D0 ;add in owTable
|
||
MOVE.L D0,D2 ;remember offset to height table for later
|
||
ADD.L D5,D0 ;add in newTable
|
||
|
||
; if the font has a built-in width table, make sure we take that into
|
||
; account
|
||
|
||
BTST #1,1(A1) ;built in width table?
|
||
BEQ.S @growTheFont ;if not, skip
|
||
|
||
ADD.L D5,D0 ;increase new size
|
||
ADD.L D5,D2 ;bump where heights go, too
|
||
|
||
; grow it to include the table
|
||
|
||
@growTheFont
|
||
MOVE.L A3,A0 ;get the font handle
|
||
_SetHandleSize ;try to grow it
|
||
BEQ.S MakeCTable ;if we can, good
|
||
|
||
; we couldn't grow the handle so give up.
|
||
|
||
DoneBCT
|
||
MOVEM.L (SP)+,D3-D7/A2-A5
|
||
RTS
|
||
|
||
; OK, D2 has the offset to the beginning of the character offset table,
|
||
; D1 has offset to locTable, D3 has firstChar and D4 has lastChar. Loop
|
||
; for the # of characters, walking down both tables, using locTable to
|
||
; build the mask, counting the rows and filling out the charTable.
|
||
|
||
MakeCTable
|
||
MOVE.L (A3),A2 ;point to font
|
||
OR #1,(A2) ;turn on mode bit
|
||
|
||
MOVE.W fFRectHeight(A2),D3 ;hold total height
|
||
ADD.L D1,A2 ;A2 points to locTable
|
||
MOVE.L (A3),A4 ;point to font
|
||
ADD.L D2,A4 ;point to charTable
|
||
|
||
; here's the start of the loop. D5 has the number of entries *2 to
|
||
; process. From the words that A2 points to, make a mask/offset combo
|
||
; in A1/D0.
|
||
|
||
SUBQ #2,D5 ;don't need extra bounds
|
||
CTabLoop0
|
||
MOVE #$FF00,(A4) ;init top to FF, bot to 0
|
||
|
||
MOVE.W (A2)+,D7 ;get locTable entry
|
||
MOVE.W (A2),D6 ;get next entry, too
|
||
SUB.W D7,D6 ;compute length in pixels
|
||
BEQ.S EmptyChar ;if zero, its easy
|
||
|
||
; Here's where we re-enter the loop for wide characters. Make A1 point
|
||
; into word of font, and start building the mask in D0.
|
||
|
||
CTab1Loop
|
||
MOVE.W D7,D2 ;remember start
|
||
MOVE.W D7,D0 ;get start in D0
|
||
LSR.W #4,D0 ;divide by 16
|
||
ADD.W D0,D0 ;double for byte offset
|
||
|
||
MOVE.L (A3),A1 ;get font pointer
|
||
ADD.W #FRowWords+2,A1 ;point to strike
|
||
ADD.W D0,A1 ;point to proper word
|
||
|
||
; now build the leftMask based on the remainder
|
||
|
||
AND #15,D2 ;compute start mod 16
|
||
MOVE D2,D1 ;copy it
|
||
ADD.W D1,D1 ;double for word index
|
||
|
||
MOVEQ #0,D0 ;clear high part of D0
|
||
MOVE.W LeftMask(A5,D1),D0 ;get leftMask
|
||
SWAP D0 ;keep in high word
|
||
|
||
; now compute how many pixels were used up in the first word, and decrement
|
||
; the width value
|
||
|
||
MOVEQ #16,D4 ;useful constant!
|
||
MOVE D4,D1 ;at most 16 used
|
||
SUB.W D2,D1 ;compute number used
|
||
ADD.W D1,D7 ;bump left index
|
||
|
||
SUB.W D1,D6 ;compute number left
|
||
BEQ.S MaskBuilt ;if none, done building mask
|
||
BPL.S @moreMask ;if >0, turn on more bits
|
||
|
||
; the width remaining is < 0, so we must turn off bits in the mask
|
||
|
||
MOVE D6,D1 ;get the delta
|
||
ADD.W D4,D1 ;compute 16-delta
|
||
ADD.W D1,D1 ;double for word index
|
||
|
||
MOVE.L RightMask(A5,D1),D2 ;get inverse mask in high word
|
||
AND.L D2,D0 ;turn off right bits
|
||
BRA.S MaskBuilt ;OK, we got it
|
||
|
||
|
||
; here we handle the case where there's more in the next word to process,
|
||
; so extend the mask into the low word.
|
||
|
||
@moreMask
|
||
MOVE.W D6,D1 ;get remaining count
|
||
CMP.W D4,D1 ;bigger than 16?
|
||
BLE.S @notTopEnd ;if not, skip
|
||
MOVE.W D4,D1 ;if so, max out at 16
|
||
@notTopEnd
|
||
ADD.W D1,D1 ;double for word index
|
||
MOVE.W RightMask(A5,D1),D2 ;get mask
|
||
OR D2,D0 ;extend the mask
|
||
SUB.W D4,D6 ;decrement remaining width
|
||
ADD.W D4,D7 ;bump index to next word
|
||
|
||
; at this point, A1 points to the top long in the character and D0 has
|
||
; the mask. D3 has the number of scan lines. Loop, fetching a long
|
||
; and masking to find top of character.
|
||
|
||
MaskBuilt
|
||
MOVE.L A1,-(SP) ;remember first pointer
|
||
|
||
MOVE D3,D1 ;init height counter
|
||
SUBQ #1,D1 ;bias for DBRA
|
||
|
||
MOVE.L (A3),A0 ;get font pointer
|
||
MOVE.W fRowWords(A0),A0 ;get rowWords in A0
|
||
ADD.W A0,A0 ;compute rowBytes
|
||
MOVEQ #0,D4 ;D4 is current top
|
||
TopMaskLoop
|
||
MOVE.L (A1),D2 ;get the bits
|
||
AND.L D0,D2 ;any relevant one on?
|
||
BNE.S MergeInTop ;if on, done with top
|
||
|
||
ADDQ #1,D4 ;bump top
|
||
ADD.W A0,A1 ;add in RowBytes
|
||
DBRA D1,TopMaskLoop ;loop for all height
|
||
|
||
; all blank so set up as (0,0)
|
||
|
||
ADDQ.L #4,SP ;strip saved A1
|
||
MOVEQ #0,D6
|
||
EmptyChar
|
||
CLR.W (A4)+ ;stick 0,0 in table
|
||
BRA.S NextChar ;go process next char
|
||
|
||
; OK, so top is in D4. Merge it into the table.
|
||
; (A4) starts at $FF, so any other value is smaller by unsigned <28May86>
|
||
; compare; we're looking for the lowest value possible. <28May86>
|
||
|
||
MergeInTop
|
||
CMP.B (A4),D4 ;is it smaller?
|
||
BHS.S @0 ;if not, skip
|
||
MOVE.B D4,(A4) ;update top
|
||
|
||
; now try the bottom up
|
||
|
||
@0
|
||
MOVE.L (SP)+,A1 ;recover character ptr
|
||
|
||
MOVE D3,D2 ;get height
|
||
SUBQ #1,D2 ;compute height-1
|
||
|
||
MOVE A0,D4 ;get rowBytes
|
||
MULU D4,D2 ;compute offset to bottom
|
||
ADD.L D2,A1 ;start with bottom word
|
||
|
||
MOVE D3,D4 ;start with height
|
||
MOVE D3,D1 ;get # of lines
|
||
SUBQ #1,D1 ;bias for DBRA
|
||
BotMaskLoop
|
||
MOVE.L (A1),D2 ;get the long
|
||
AND.L D0,D2 ;any relevant bits on?
|
||
BNE.S MergeInBot
|
||
|
||
SUBQ #1,D4 ;one less high
|
||
SUB.W A0,A1 ;back up a scan line
|
||
DBRA D1,BotMaskLoop
|
||
BRA.S EmptyChar ;impossible to get here...
|
||
|
||
; compute the height of the character and merge it in
|
||
; Herein lies the bug: until now the delta was computed along the <28May86>
|
||
; way, so information could be lost about characters that slanted <28May86>
|
||
; from lower left to upper right. Nowadays, keep the low point in the <28May86>
|
||
; second byte until the character is finished; then compute the delta <28May86>
|
||
; into the second byte.
|
||
|
||
MergeInBot
|
||
ADDQ.L #1,A4 ;skip top offset <28May86>
|
||
CMP.B (A4)+,D4 ;compare with last height
|
||
BCS.S NextChar ; <28May86>
|
||
|
||
MOVE.B D4,-1(A4) ;its bigger, so use it
|
||
|
||
; we're finally done with this band of the character (at least!) so see
|
||
; if we're really done with it
|
||
|
||
NextChar
|
||
SUBQ.L #2,A4 ;back up
|
||
TST D6 ;done with this character?
|
||
BGT CTab1Loop ;if not, dive in again
|
||
|
||
; Get here when finished with a char. Have high and low pts in (A4), <28May86>
|
||
; so must compute low-high in 1(A4) as incrementing. <28May86>
|
||
MOVE.B (A4)+,D0 ;high pt <28May86>
|
||
SUB.B D0,(A4)+ ;low-high <28May86>
|
||
SUBQ #2,D5 ;more to do?
|
||
BGT CTabLoop0 ;if so, go do it
|
||
BRA DoneBCT ;if not, we're done
|
||
|
||
FMgrEnd
|
||
|
||
;*******************************************************************
|
||
;*******************************************************************
|
||
;*******************************************************************
|