mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-12-03 00:51:48 +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
|
|||
|
|
|||
|
;*******************************************************************
|
|||
|
;*******************************************************************
|
|||
|
;*******************************************************************
|