sys7.1-doc-wip/Toolbox/FontMgr/FontMgr.a
2020-04-26 16:46:44 +08:00

5495 lines
231 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Reverted all three changes in <73> (<73>.1 etc). Reverted <71> fix to
; style search code. Reverted <SM22> change that got ScrnBase directly
; from lowmem instead of QD globals. Commented out <SM19> RomMapInserts
; for fctb/FOND/NFNT resources. Restored a missing HAS_COLOR conditional
; around 'color strike' caching code. Unlengthened one branch, likely from
; <SM17>. Unshortened several branches. Made all patch routines self-
; installing with separate MakePatch macros on color and B&W machines.
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
;—————————————————————————————————————————————————————————————————————————————————————————————————————
;
; File: FontMgr.a
;
; Copyright: © 1983-1993 by Apple Computer, Inc., all rights reserved.
;
; Scaling Font Manager for MacIntosh User Interface ToolBox
;
; written by Andy Hertzfeld February 5, 1983
;
; New 128K ROM version, AJH, last week of April 1985
;
; Here it is, the new scaling font manager which supports independent
; typeFaces and sizes. The font manager is built on top of the
; resource manager and provides a simple swapping mechanism for fonts,
; based on the resource/memory manager's purgable objects. It is passed
; an input record from QuickDraw consisting of the font face, device, style
; and scale and selects the closest font to the requested size that it can.
; It is optimized so that it is very fast if the request is the same as the
; last time.
;
; Printer support is provided via two control/status calls defined by the font .
; manager. After it figures out what everything should be, it gives the
; appropriate device a control call to let it change things. Also, it makes
; a status call to get a table of style values to aid in in figuring things out.
;
; Major changes for the new (128K) ROM include a new font addressing
; scheme using family definition records as resource type "FONT",
; which allows up to 64K different font families and tweaked fonts for
; bold, italic, etc. Fractional widths are fully supported.
;
; Change History (most recent first):
;
; <SM23> 7/6/93 kc Roll in Ludwig.
; <LW2> 5/21/93 KW (SM20 CSS) Update from Reality for Truetype bug fixes post 7.1:
; (74 DTY) Move ScriptPriv.a out of a non-ROM conditional area to
; get Font2RealScript. Also, for ROM builds, change a word branch
; to GetDevPix to a jsr, now that GetDevPix in Color Quickdraw is
; too far away to branch to. (73 YK)
; #PartOfWSIIFix,1053866,1053919: Double-Byte TryeType font, which
; usually has relatively large LowestPPEM value, has trouble in
; small point size on Cube-E. 1. If sfnt is the only installed
; font resource (no NFNT), always use it even if the requested
; size is smaller than the LowestPPEM. 2. When trying to find the
; closest size of NFNT reosurce, dont take sfnt as Zero-point
; NFNT. 3. Call the Script Manger, instead of masking a font id,
; to get the system script font. (71 DTY) Fix
; GetFONDForSizeAndStyle to use correct style when styles are
; split across multiple FONDs.
; <SM22> 5/28/93 kc Change GetPixelDepth to get the base address of the screen from
; low memory instead of the QuickDraw globals. On Cyclone, the
; base address changes on depth switch, and StupidDraw doesn't
; update the QuickDraw Globals. InitGDevice should be changed to
; update the QuickDraw Globals for every running process.
; <SM21> 5/27/93 CSS Roll out <71> from previously rolled in from Reality because it
; was rejected in the Cyclone code review.
; <SM20> 5/21/93 CSS Update from Reality for Truetype bug fixes post 7.1:
; <74> 3/30/93 DTY Move ScriptPriv.a out of a non-ROM conditional area to get
; Font2RealScript. Also, for ROM builds, change a word branch to
; GetDevPix to a jsr, now that GetDevPix in Color Quickdraw is too
; far away to branch to.
; <73> 3/29/93 YK #PartOfWSIIFix,1053866,1053919: Double-Byte TryeType font, which
; usually has relatively large LowestPPEM value, has trouble in
; small point size on Cube-E.
; 1. If sfnt is the only installed font resource (no NFNT), always
; use it even if the requested size is smaller than the
; LowestPPEM.
; 2. When trying to find the closest size of NFNT reosurce, dont
; take sfnt as Zero-point NFNT.
; 3. Call the Script Manger, instead of masking a font id, to get
; the system script font.
; <71> 1/11/93 DTY Fix GetFONDForSizeAndStyle to use correct style when styles are
; split across multiple FONDs.
; <SM19> 11/19/92 RB Set ROMMapInsert to MapTrue just before doing some GetResource
; calls so that we look in ROM first.
; <SM18> 11/12/92 PN Get rid of ≥ 020 conditionals
; <SM17> 10/22/92 CSS Change some short branches to word branches.
; <70> 9/2/92 DTY Use records for the synthetic font labels.
; <69> 9/1/92 DTY Use a record for stack frame offsets.
; <68> 8/17/92 DTY #1039825 <csd>: Ill get it right one of these days… If were
; remembering an alternate font and we determine that weve
; already picked up an alternate, dont bail immediately. Instead,
; branch to a point in the code which decides whether we need to
; keep looking for an exact match, or if we actually can leave.
; <67> 8/13/92 DTY #1039692 <BBM>: #1039692 <BBM>: The last two changes made the
; Font Manager stop looking for an exact match too soon. It
; stopped looking after it found a possible match. Make it keep
; looking until it finds an exact match, or it runs out of fonts
; to look at.
; <66> 8/7/92 DTY Need to mark the requested style as non-plain for splines as
; well.
; <65> 8/6/92 DTY #1039047: If using a styled bitmap even though plain was
; requested, change the requested style to be non-plain so that
; GetFONDForSizeAndStyle knows which register to return the 'FOND'
; from.This is another Dean is a bonehead bug. This happens only
; if you copy the application font into the destination suitcase,
; and the Finder updates some windows after the Mover progress
; dialog goes away. In the Font Manager, if a styled bitmap was
; being used as a QuickDraw plain face, GetFONDForSizeAndStyle
; would return the saved 'FOND' from the wrong register, and wind
; up nilling out the resource chain.
; <64> 7/31/92 DTY #1037497 <gbm>: The last change had a bug which caused an
; infinite loop if QuickDraw wants a size that doesnt exist, and
; there is no other style to fall back on. Add some code which
; knows how to get out of this case.
; <63> 7/24/92 DTY #1037497 <gbm>: Added code to GetBestFONDForSizeAndStyle to
; remember styled 'FOND' entries if QuickDraw is asking for a
; plain style. This is so that styled fonts can be rendered in
; their own face instead of the application font. Adding this
; code allows styled fonts to be plain versions of themselves in
; addition to being styled versions of the base font.
; <62> 7/21/92 DTY #1036674: #1036674: Test D0 after the call to ReallocHandle to
; restore the condition code after restoring the zone.
; <61> 7/20/92 DTY #1035869: Be a little more lenient about bonehead 'FOND'
; resources. Bail early in GetCandidateFONDs if the entry count in
; the font association table is negative.
; <60> 7/17/92 DTY #1036422 <pvh>: Locking the candidate list while Im walking
; through it in RealFont would be nice…
; <59> 7/11/92 DTY #1035746 <gbm>: In GetBestFONDForSizeAndStyle, mark the
; candidate 'FOND' non-purgeable so it doesnt get purged when a
; large TrueType font is loaded.
; <58> 7/8/92 DTY #1035322 <csd>: In GetBestFONDForSizeAndStyle, check to see if
; an alternate font has already been remembered before remembering
; a new alternate.
; <57> 7/2/92 DTY #1034530: ReAllocHandle will reallocate handle blocks in the
; current heap, even though the master pointer may be in a
; different heap. Make sure that the system zone is the current
; zone before calling ReAllocHandle so that the width tables are
; always in the system heap.
; <56> 6/30/92 DTY #1034346 <pvh>: In GetCandidateFONDs, if the font number passed
; in is applFont, grab the real font number out of ApFontID so
; that GetResource will succeed.
; <55> 6/29/92 DTY #1031203: #1031203: Dean is brain damaged. The last change winds
; up not looping through the resource chain at all.
; <54> 6/23/92 DTY #1031203: Suitcase has a patch on GetResource that makes it
; start searching from the top of the resource chain, if Suitcase
; is the current resource map. This breaks GetCandidateFONDs,
; which doesnt expect to get a resource from higher up in the
; chain than the current resource map. Added a check that
; collects FOND resources to bail if the end of the resource chain
; is reached before the map containing the FOND resource is found.
; <53> 6/23/92 DTY #1031450: The previous change to RealFont added a call to
; fs_LowestPPEM to determine if TrueType can be used for a
; particular point size. The point size is kept in register D2,
; but D2 can be trashed by Toolbox calls. Like fs_LowestPPEM.
; Save and restore D2 around the call to fs_LowestPPEM.
; <52> 6/12/92 DTY #1032393 <FM>: RealFont needs to set CurMap before calling
; LoadSplineFontResource in case the current resource map is below
; the resource file that the font came from.
; <51> 6/8/92 SAH #1031825: No longer use arithmetic mode bit as a signal that we
; need to colorize (this used to be passed to MakeScaleTbl to tell
; it to colorize, but MakeScaleTbl no longer uses this bit). This
; means that synthetic fonts created with an arithmetic mode are
; now black and white, rather than black and white but marked as
; color. Also changed to create synthetic fonts for not modes.
; <50> 6/5/92 DTY #1031450: In RealFont, if weve got a TrueType font, dont
; automatically return true. Instead, call fs_LowestPPEM first to
; make sure this is a font size that TrueType will be used for.
; <49> 6/3/92 DTY #1031058: Normally, the font association table in a 'FOND'
; resource is structured such that for a given point size, the
; entry for the plain font comes before the entries for any
; stylistic variations. The candidate caching code saves
; information about the fonts in the font family, keeping a record
; of the plain font, and a record for all the styles. It assumes
; that the font assocation table followed the normal ordering. Of
; course, were talking about Macintosh developers here, who are a
; breed apart and theres always ONE person that doesnt follow
; the standard. Add a check so that if one of these screwy
; 'FOND's is encountered, the record for the styles is split
; across the record for the plain entry. What Im saying is that
; the cache entries used to look like: [Info for plain][Info for
; styles]. For a screwy 'FOND', it will look like: [Info for
; styles][Info for plain][Info for more styles].
; <48> 6/2/92 DTY #1030818 <csd>: The check in FindSize for a double byte font
; assumes that all script systems after smKorean will be double
; byte. This causes Arabic and Hebrew TrueType to not work because
; the call to fs_LowestPPEM fails due to the lack of a fragment
; table.
; <47> 5/4/92 DTY #1029119: In GetFONDForSizeAndStyle, ignore the high byte of the
; style word when matching for a style, since this byte contains
; color information, and we dont care about that at this point.
; <46> 4/24/92 DTY Case Obj sucks. Dont use Case Obj for ROM builds.
; <45> 4/24/92 DTY TrueType™ lives! Remove all the hasSplineFonts and Gaudi
; conditionals.
; <44> 3/31/92 DTY #1024665,<FM>: Change all the one deep Resource Manager calls
; back to the n deep ones since were gauranteeing unique IDs for
; all font resources.
; <43> 3/27/92 DTY #1025750: In GoLoadStrike, if the code path reaches @loadFailed,
; restore d6 and d7 before branching to FindSize.
; <42> 3/20/92 DTY #1025041: Re-write GetFONDForSizeAndStyle so its much easier to
; read and understand.#1025041,<pvh>: Improve
; GetFONDForSizeAndStyle so its easier to follow and understand.
; <41> 3/17/92 DTY GetCandidateFONDs puts a long into CurMap, smashing ResReadOnly.
; <40> 1/22/92 DTY Take out all the changes to the synthetic font code from <29>.
; Were gauranteeing that font resources will always have unique
; IDs.
; <39> 1/15/92 DTY FONDMap is a long, not a word, hosehead! Get the reference
; number by dereferencing FONDMap.
; <38> 1/11/92 DTY #1019573: GetStrike now uses a stack frame, but a stack frame is
; not set up when GetStrike is called from _RealFont. Set up a
; stack frame around the call to GetStrike in _RealFont. Also, in
; GetFONDForSizeAndStyle, make sure that a 'FOND' resource that
; is being checked for the desired size and style is actually
; currently in the resource chain before trying to use it. If the
; resource map containing a 'FOND' is not in the chain, that
; 'FOND' is skipped.
; <37> 12/20/91 DTY In GetCandidateFONDs, start building the candidate list from
; TopMapHndl instead of CurMap.
; <36> 12/18/91 DTY #1018428: Dont assume that FindSize found the font resource.
; Check the condition codes when it returns to see if scaling will
; be necessary.
; <35> 12/13/91 DTY This is what I get for mixing old code with new code.
; GetFONDForSizeAndStyle looks at D2 at the very end to set the
; codes for whether or not to look for another font, or to try to
; scale another size. D2 should have the last size entry in the
; font association table. Errrnnk!
; <34> 12/13/91 DTY The last fix caused MakeMapOneDeep to be called twice in some
; instances, which effectively destroyed the copy of the real
; attributes in D7. Check the contents of D7 before the second
; call to determine if MakeMapOneDeep should called again.
; <33> 12/10/91 JH Fixed bug in GoLoadStrike that was causing a crash when the
; keyboard menu was pulled down. Basically if the font needed to
; draw in the menu is a spline font GoLoadStrike will call
; _sbPreFlightFontMem which loads the spline and if everything is
; OK branches to @splineOKay. The problem with this is that
; eventually the code at @splineOkay ends up branching to WeGotIt
; which always calls RestoreMapAttributes which expects d7 to
; contain the old map attributes. If the spline font was
; successfully loaded the attributes never got saved in d7 so we
; restore trash, hmmm. Fix was to call MakeMapOneDeep, which sets
; d7 correctly, before branching to splineOKay. If I was Pete I'd
; say thanks Dean, but I'm not so I won't.
; <32> 12/2/91 DTY Lets derefence the TrueType global handle before we use it…
; <31> 11/22/91 JH Rolling in Kon's changes from Sakura project. Added code to
; FindSize utility routine to check if the font is an asian font.
; If it is we check splinepreferred if that is true use the old
; Roman logic. Next check to see if requested size is bigger than
; the mimimum size allowed in LowestPPM. If requested size is less
; than we use the bitmap. Change begins at @gotSpline label and
; ends at ST WidthIsSpline(A1).
; <30> 11/19/91 DTY Another check is needed in GetFONDForSizeAndStyle to return the
; plain spline before the styled spline. Also, dont call
; MakeMapOneDeep in LoadSplineResource, since LoadSplineResource
; is called from other places in the code that dont set things up
; properly. Instead, just set up CurMap from lastFontMap and hope
; for the best.
; <29> 11/15/91 DTY Save the resource map attribute bits upon entry into GetStrike,
; since it might not fall through from LoadStrike. (This means
; restoring the bits before falling through from LoadStrike.)
; Also store the font family ID in each synthetic font record
; entry, since the synthetic fonts are tagged by font ID, but
; fonts are allowed to have duplicate IDs in the Fonts folder, so
; further differentiation is needed.
; <28> 11/9/91 DTY Delay the restoring if the real CurMap until after an attempt to
; fetch the styled font resource.
; <27> 11/3/91 DTY The FOND stored in LastFOND may be different from that FOND that
; is actually returned by GetFONDForSizeAndStyle. Jam the FOND
; that is used into LastFOND in this routine.
; <26> 10/25/91 DTY Erk. I left a _Debugger in the source.
; <25> 10/25/91 DTY Ooops again. Need to bump past the FOND ID in the candidate
; list when trying to scale a font.
; <24> 10/25/91 DTY Ooops. GetFONDForSizeAndStyle doesnt restore D4 and D5 if a
; font wasnt found. Sorry Kon.
; <23> 10/25/91 DTY GetCandidateFONDs is still looking in TopMapHndl instead of the
; current map. (Everything else was changed in the last revision,
; but I missed this case.) Also, some additional checking to
; determine whether to use the plain or styled font is needed in
; GetFONDForSizeAndStyle if a TrueType font is to be used.
; <22> 10/24/91 JSM Include ResourceMgrPriv.a for ROM builds so they keep working,
; although this isnt a real good solution.
; <21> 10/23/91 DTY Brian lied. The Resource Manager doesnt stop at SysMapHndl.
; Stop slamming TopMapHndl to get around what doesnt happen.
; LoadStrike now calls _GetMap to get the current resource map
; instead of peeking at TopMapHndl.
; <20> 10/22/91 DTY Make sure to use TrueType fonts if splinePreferred is set, even
; if a bitmap was found first. (But keep the bitmap around in
; case a TrueType font isnt found.)
; <19> 10/21/91 DTY One deep resource calls should be one deep resource calls.
; Clear the twoDeepBit in the resource map before trying to load a
; font. (Dont you just love how the Resource Manager and the Font
; Manager have their hands all over each other?)
; <18> 10/14/91 DTY Make GetCandidateFONDs use the application font if the requested
; font family couldnt be found. Make _RealFont use
; GetCandidateFONDs to determine if a size is available instead of
; patching it. (The _RealFont patch in FontFolderPatches.a is
; gone.) Also load the resource in FindSize if the font was
; purged.
; <17> 10/11/91 DTY Building the candidate FOND list takes too long. Cache two lists
; in SplineKey. Also added check for styled TrueType font in
; GetFONDForSizeAndStyle.
; <16> 10/10/91 DTY Change GetCandidateFONDs to include styles in the list it
; builds, and have GetFONDForSize consider the style thats needed
; during its search as well.
; <15> 10/4/91 DTY Font resources can have duplicate IDs in the font chain. They
; may lead to the wrong font being loaded if the font type is not
; found in the current map, but is found in a lower map. Use one
; deep resource calls in LoadStrike and LoadSplineFont to avoid
; this. Fixed bug in GetCandidateFONDs which didnt know when to
; stop walking the resource chain, and wound up going through 0.
; Also fixed bug in LoadSplineFont which caused it to bail even if
; a spline was actually loaded.
; <14> 9/25/91 jlf Rolled in modifications from Pacific TrueType project:
; Replaced GetResource calls for 'sfnt' resources with
; a procedure call to LoadSplineFontResource. Added
; LoadSplineFontResource to not load 'sfnt' resources
; greater than 128k (Asian fonts can be as large as
; eight megabytes). Modified SetFontLock so that it
; calls LoadSplineFontResource instead of LoadResource.
; Added conditional (hasSplineFonts) or (Gaudi) code
; after DoStyle - code was loading sfnt resources and
; treating them as 'FONT'/'NFNT' resources. Solution
; is to check WidthIsSpline field in the current
; widthtable and bail to noColors if true.
; <13> 9/19/91 DTY Teach _FMSwapFont about the Fonts Folder. Change NewFontLookup
; to call a new routine which finds all occurences of a 'FOND' in
; all open font files, and gets all the sizes in those 'FOND's.
; NewFontLookup uses this information to find the right size
; instead of examining the Font Association table inside the
; 'FOND'.
; <12> 7/10/91 JSM Remove obsolete SysVers conditional.
; <11> 6/12/91 LN added #include 'SysPrivateEqu.a'
; <10> 2/22/91 CL JT: Fixing synthetic font building. Just using sethandlesize to
; make sure there is enough space instead of purgespace.
; <9> 2/13/91 KON CEL, SMC: BRC #unknown: FMSwapFont derefernces a handle and then
; calls SetHandleSize. This was causing crashes when Heap Scramble
; was turned on. Now the Handle is locked before calling
; SetHandleSize.
; <8> 2/11/91 RB [MR,CD,CC] Redereference FOND handle when walking it inside
; RealFont after loading an sfnt. Jam the width of <cr> to zero,
; inorder to make FractEnable on/off widths consistant between
; bitmaps and outlines.
; <7> 1/8/91 CL (GM) In the RealFont routine… Need to check in the rom for the
; sfnt. Setting ROMMapInsert to true before the getresource call.
; <6> 1/7/91 csd & gbm; Removed the conditional around the code that calls
; InitFonts if the widthTabHandle is NIL. We want this in case we
; get a volume remount (or other) dialog before the application
; has called InitFonts.
; <5> 11/28/90 CL Fixing MakeITab branch. Cannot be short.
; <4> 11/28/90 CL (RB)Must still look for extra widths for sfnts when style width
; tables are in the FOND. You can only use these for bitmap fonts.
; <3> 10/30/90 CL (MR)Adding in fs_LowestPPEM to realfont.
; <2> 10/22/90 CL (BKR) Adding fontHandle to preflight call.
; <30> 10/9/90 CL Adding call to preflight routine to make sure the loaded sfnt
; leaves enough space for the font scaler.
; <29> 10/8/90 CL Added code that when failing to load in an sfnt tries again for
; a bitmap font of that family.
; <28> 9/27/90 CL Needed to add the numer and denom fill back into the spline case.
; <27> 9/27/90 CL Backing out Bold style extra fix. Need to re-evaluate the
; consequences.
; <26> 9/26/90 CL In fractenable when using an outline font the Bold style extra
; was not being set up since the fontmgr thought it would get the
; widths out of the FOND width table. All widths always come from
; the sfnt in the outline font case. So the style extra must be
; set with the algorithmic extra that QuickDraw is using.
; <24+> 9/24/90 CL Matching up the spline caches at the end of FMSwapfont.
; <24> 9/23/90 CL Fixing conditionalized branch
; <23> 9/22/90 CL The boolean FractEnable when sent to sbFillwidthtab must have
; the value in the high byte of the word.
; <21+> 9/20/90 CL Accidently skipped some code that filled out part of the width
; table values. One important one was the fSize field which
; effected the charExtra type routines.
; <21> 9/18/90 CL Fixing a bug that jumped out of the difFont loop. Bad
; idea since we would not do the unlink.
; <20> 9/17/90 BG Fixed up log message for <19> since the CheckWindowIn CANCEL
; button doesnt work correctly yet.
; <19> 9/17/90 BG Removed <13>. 040s now work more reliably.
; <18> 8/31/90 CL The font may be purged before getting to the sb_FillWidthTable
; or sb_SearchForCache call. This should not happen since both
; routines expect the font to be there. So load the font in
; before calling these routines!!!
; <17> 8/24/90 CL The font manager did not create 16 or 32 bit fonts. Instead it
; pinned the syn fonts to 8 bit. The only problem to this is that
; it tried to use the device color table. Since it was 16 or 32
; bit dest but the source was 8 bit the table certainly did not
; match. Now it uses the original data and its 'fctb' in 16 or 32
; bit mode.
; <16> 8/16/90 CL Problem: A synthetic font some times would not be created
; correctly. Reason: D3 register was expected to be set up to the
; source depth. When a font that was smaller than the original
; data was not found, D3 never got set up. The font building
; created a bad syn font. Solution: We made sure we always set up
; D3 before creating the font.
; <15> 7/27/90 CL Added SetFScaleDisable and SetFractEnable back in for Black and
; White machines for the TrueType™ build.
; <14> 7/25/90 CL When a get resource on an sfnt fails A0 may be invalid so
; setting isSpline off of A0 is not a good idea at all. Now it is
; fixed.
; <13> 7/20/90 BG Added EclipseNOPs for flakey 040s.
; <12> 7/20/90 DTY Bass: The Linked Patch. Added condition Black and White
; procedure names, added Gaudi variable to checks for SplineFonts,
; and moved in GetDevPix from BassComm_Tail. (You mean thats
; it?!?)
; <11> 7/16/90 CL FMExist does not exist on the MacPlus so it cant be checked in
; initfonts for this cpu.
; <10> 6/29/90 CL Took out swap cache flag to make sure the sb_searchforcache
; always gets called to insure the correct font cache is loaded.
; <9> 6/22/90 CL Checking in changes for CHAZZ… Took out cache handles
; from the width table. Only one global cache at a time.
; It is simplier. Took out run time checks for hasColor
; since the fontmgr is now compiled for either B&W or
; Color.
; <9> 6/22/90 CL Created new equate file fontPrivate.a with includes from this file and
; SplineDefines.
; <8> 5/29/90 CL Checking in changes for CHAZZ… Took out cache handles from the
; width table. Only one global cache at a time. It is simplier.
; Took out run time checks for hasColor since the fontmgr is now
; compiled for either B&W or Color.
; <7> 4/18/90 CL Taking out special case for disk caching since the routine
; called is already conditionalized. Fixed conditionalize for
; SPLINE_FONT to be hasSplineFonts like it needs to be.
; <6> 4/16/90 HJR Change SPLINE_FONTS to hasSplineFonts
; <5> 4/10/90 CL Adding in ROM conditionals for Elsie. If the spline key is not
; set up we will never choose a spline font from the font
; association table.
; <4> 3/20/90 CL Support for tag sfnt format…
; <3> 2/28/90 CL Fixed include for rom builds. Needed to replace inc.sum.a with
; StandardEqu.d.
; <2> 2/27/90 CL Added support for DrText optimizations
; <4.1> 11/28/89 CEL Justification bug in spline fonts was caused by one extra space
; adjustment.
; <4.0> 10/27/89 BAL forJP: Forgot to make InitFonts RTS to caller, silly me.
; <3.9> 10/27/89 BAL Only define Spline_Font if currently undefined. Also added the
; forJP conditional.
; <3.8> 9/25/89 CEL Took out actual face adjustment for Spline fonts. Now works the
; same as bitmaps.
; <3.7> 9/15/89 CEL Re-doing calling conventions to make them pascal.
; <3.6> 8/28/89 PKE In InitFonts, finish by jumping to Script Manager code
; <3.5> 8/28/89 CEL Fixing Bass outline font scaling values. Fixed SpExtra in
; <3.4> 8/14/89 CEL Spline Fonts does not include PatchMacs.a anymore. Added in
; <3.3> 6/28/89 GGD Fixed link problems by using BigJMP to SMgrInitFonts,
; <•3.2> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw
; <3.1> 5/26/89 CEL Integrated the new Font Scaler 1.0 into Spline Fonts
; <3.0> 5/5/89 CEL Fixed colorgray value for Bass patch. This does not affect
; <•2.9> 5/5/89 CEL Moved label outside of conditionals so system would build,
; <•2.8> 5/4/89 CEL Cleaned up conditionals for ROM
; <•2.7> 5/3/89 CEL Bass rolled into ROM. NOTE:Spline Fonts are conditionalized
; <•2.5> 5/1/89 cel Rolled in Bass…
; <1.8> 4/4/89 CCH Fixed out of range branch.
; <1.7> 4/3/89 cv Rolled in several patches including all new routines in the
; <1.6> 2/28/89 PKE Restored Script Manager mod to InitFonts, which somehow
; <1.5> 2/20/89 rwh changed from machine-based to feature based conditionals.
; <1.4> 2/15/89 CCH Changed LOAD of inc.sum.d to INCLUDE of inc.sum.a.
; <•1.3> 2/15/89 CCH Adding to EASE for 32-bit quickdraw from sources from
; 5/9/88 BAL Altered depth scaling code to use long sized pixel translation
; table.
; 5/8/88 BAL Tweek code to allow pixel sizes up to 32 bits.
; 6/4/87 CRC Sorry, Jerome, but I took your patch right out again. The
; curious comment on 20-Feb-87 allows zero sized fonts for font
; names, only. For all other font references, the font resource
; must be at least 24 bytes long. But, since GetHandleSize on an
; empty handle is a faux pas, I changed it to MaxRsrcSize.
; <PB164> 6/2/87 JTC Roll in patch to bypass GetHandleSize after GetResource, as
; curiously mentioned in 20-Feb-87 above.
; 2/20/87 CRC Skip GetHandleSize check after a GetResource from GetFName, so
; that zero size fonts are allowed
; 1/31/87 CRC make FONDs nonpurgable in cache case; let condense, extend go
; multi-bit; use 1 bit font in “not” srcBic modes, look for second
; best multibit font, dont color srcXor, allow font sizes > 127
; 1/3/87 CRC if less than 3K stack, or if dest. is 1 bit, skip color cache
; 12/21/86 CRC use normal foreground/background color with arithmetic modes
; 12/4/86 CRC if fond can not be had, try old way first before substituting
; 12/4/86 CRC cache case short circuit moved so that FOutExtra is set up
; properly; initialized fWidStyle
; 12/2/86 CRC can only return FOND widths only if fractional widths are
; enabled.
; 11/24/86 CRC three bugs: register across FixMul; inval FondID; A3
; save/restore in DifStyle
; 11/11/86 CRC large font from Professional Composer pointed out bug (missing
; .L) in synthetic font build
; 11/10/86 CRC OK, lets try forcing the synthetic strike list handle in the
; sysZone instead.
; 11/10/86 CRC clear FOutFontHandle in InitFonts only in fmExist false case;
; skip widths if only colors, modes, depth changed; get the depth
; from the current port, and the gDevice only if old bitmap & on
; screen
; 11/8/86 CRC force synthetic strike list handle to be allocated in the
; applZone (Turbo Pascal)
; 10/30/86 CRC save original font request less needBits rather than
; substitution record
; 10/24/86 CRC inval width table in system heap full case; made some stack
; locals conditional for Becks.
; 10/20/86 CRC fixed check LastSpExtra before CurFMFamily in DoMapFont bug
; 10/17/86 CRC moved some equates to nToolEqu; just test fgColor/bkColor in
; fast case added fmExists to allocate structures once per
; application, some code cleanup
; <C206> 10/9/86 bbm Modified to mpw aincludes.
; 9/26/86 CRC fixed MacWrite bug; called InitFonts before InitGraf
; 9/24/86 CRC code cleanup from Jerome/Donn/Erich/Andy review
; 9/17/86 CRC Color, gray scale font support
; 9/16/86 CRC Added condition for JSwapFont set up for trap table
; 9/15/86 CRC Separated screen widths from screen strikes in style selection.
; 8/22/86 CRC InitFonts uses SwapFont to get system font. made JSwapFont just
; a copy of trap table entry rolled GetResource FONT and FOND
; together. Reused GotStrike to hold fond flags rather than high
; byte of WidthListHand
; 8/12/86 CRC Revamped caching code, made family/size substitution happen
; everywhere, changed substitution algorithm. Fixed bug in style
; font selection. Backed off MyFixMul, MyFixRatio optimizations.
; 7/15/86 WRL Corrected address compare to check 24 bits only.
; 5/28/86 JTC (1) Patched GetFDefHandle to restore MemMgr bits only if master
; ptr is non-Nil. (2) Patched FontMetrics to get num/denom right.
; (3) Fix bug in height table loop for wide, tall fonts.
; 4/10/86 JTC Rolled in missed patch to GetFontName, invalidating the cache
; doubly, by setting LastSPExtra to -1.
; 2/19/86 BBM Made some modifications to work under MPW
; 1/13/86 JTC Rolled in SwapFont patches to set CurFMInput to -1 when
; FMSwapFont is and to force the WidthVFactor to be 1,1 when
; scaling is on.
; 11/6/85 DLD Took out the hack to remember a font's size in case it purged
; (Resources tell me).
; 11/6/85 DLD Conditionally check for a non-screen device when computing Extra
; before MakeWTab.
; 11/6/85 DLD Added a bit in the FOND to allow use of Family Extra with
; FractEnable False (MakeWTab).
; 10/30/85 DLD DoWTable does FScale to the missing width characters.
; 10/28/85 DLD InitFonts clears FScaleDisable and FractEnable
; 10/24/85 DLD Added code to fix the bug with switcher. Invalwidths puts -1
; into LastSPExtra to keep us from matching in the short case.
; 10/22/85 DLD Fixed disk switched font bug - CurFMFamily set to -2 to disable
; WidthTabHandle when we call ourselves via GetResource and disk
; switched hook.
; 10/18/85 DLD Now check if someone wants to invalidate the width cache
; (CurFMInput = -1 to invalidate).
; 10/18/85 DLD Changed NewEQU to put WidthTabHandle in a non-switched location.
; 10/17/85 DLD Changed ComputeFractExtra to use WidthASize - actual font size
; for "style extra".
; 10/17/85 DLD Now I mask off the high byte of WidthListHandle before checking
; if it's nil.
; 10/16/85 DLD Moved the Move.L #WidTabSize,D0 outside the loop in DoMapFont.
; 10/16/85 DLD Put a redundancy check on the font handle into DeRefResource
; 10/10/85 DLD Changed InitFonts to Call GetTrapAddress to pick up a custom
; SwapFont routine.
; 10/10/85 DLD Changed BuildCharTable to not special case RomFont0, since it
; may be custom.
; 10/10/85 DLD Changed InitFonts to check if it couldn't get a system font, and
; use Chicago.
; 10/10/85 DLD Cut down the number of extra width tables to 12.
; 10/10/85 DLD Changed InitFonts to not set or clear FScaleDisable or
; FractEnable.
; 9/27/85 DLD Added DEF to FMSwapFont, since it was removed with QuickGlue
; recently.
; 9/25/85 DLD Fixed a bug in DoMapFont (@3) where I derefed LastFOND even if
; it was Nil.
; 9/24/85 DLD Changed MapScale to loop on 2X and .5X scaling, so 4X, 8X will
; work
; 9/24/85 DLD Changed SetScaleDisable to invalidate all width tables.
; 9/24/85 DLD Rewrote FontMetrics to use fonts info, and compensate for scale
; and style.
; 9/24/85 DLD Fixed a bug in GetFontName, calling GetFDefHandle with MapFalse
; didn't load the FOND so it would return EQ. Now I invalidate
; LastFOND, FONDID.
; 9/24/85 DLD Changed SetFontLock to make the FOND purgable and non-purgable
; too.
; 9/20/85 DLD Changed the extra for Italic to 0, because old ROMs patch it to
; 0.
; 9/12/85 DLD Fixed a bug printing in hires with FOND's. We use actual size in
; GotXWidth2.
; 9/11/85 DLD Changed CheckPurged to handle the case of a released (disposed)
; font.
; 9/10/85 DLD Added logic to find FOND neighbors when all members of a family
; are gone.
; 9/3/85 DLD Extended the format of a width table (in memory)
; 9/3/85 DLD Added logic to maintain 2 width tables, when there's room.
; 8/20/85 DLD Added MyFixMul and MyFixRatio to skip trivial operations
; 8/20/85 DLD Coded an in-line FixRound, since it's easy.
; 8/19/85 DLD Made GetFDefHandle cache FondID even when no FOND found
; 7/9/85 EHB Added setup of ROMMapInsert for ROM resources
; 7/3/85 AJH Fixed RealFont "only one" bug Larry found
; 7/1/85 AJH look for NFNT then FONT, use scale factor in Metrics
; 6/28/85 AJH new fields in header for Bayles; NFNT -> FONT, more res in
; famWid tables, skip 2X for FScaleDisable, added UsedFWidths
; 6/24/85 AJH Got rid of bold extra, added italic extra (1 pixel)
; 5/30/85 AJH Made it not call FixMul unless it has to
; 5/21/85 SC Made font scaling disabled as default
; 5/14/85 SC Made FScaleDisable search down first and then up for old fonts
; and then stop search(if found) on new fonts
; 5/14/85 SC Fixed D3 bug in GetFNum that Ernie found
; 5/10/85 AJH Added FScaleDisable width correction; widMax to metrics
; NewFontLookUp search order changed; SetScaleDisable
; 5/10/85 SC Added FScaleDisable vertical correction
; 5/9/85 AJH added font->NFNT; new FOND format; family widths FractEnable and
; FontMetrics.
; 5/8/85 AJH SwapFont must rebuild WidthPtr each call; removed "numer low
; bits mask" fudge
; 5/8/85 AJH SpaceExtra changing should block "short-circuit"
; 5/7/85 AJH Fixed bugs in width table "adjust" cases
; 5/6/85 AJH Added width table support; saved FOND purged state
; 5/2/85 AJH Added checks for font IDs >= 512
; 4/30/85 AJH Added single-element FOND cache; optimized initial compare;
; removed RightMask table
; 4/22/85 AJH New ROM overhaul.
; 8/31/83 AJH fixed scaling bug Owen found (introduced 15-Aug)
; 8/29/83 AJH changed MOVEM to MOVE at SwapDone
; 8/29/83 AJH used "IOQElSize" for control and status calls
; 8/15/83 AJH Speed-optimized most common case by saving less registers some
; minor code crunching, too
; 8/13/83 AJH Fixed bug introduced by yesterday's changes (ReturnNilString)
; 8/12/83 AJH Saved code in GetFontName per Jerome's suggestions
; 7/13/83 SC Fixed bugs in lockfont
; 6/11/83 AJH made it prefer 2X and .5X scaling
; 5/11/83 AJH made GetFNum turn resource loading back on
; 4/28/83 AJH made it test resErr and substitute system font if error
; 4/6/83 AJH made GetFontName substitute for font 1
; 4/4/83 AJH made it use parameter RAM to init default font
; 4/3/83 AJH 7 bits for size instead of 6
; 3/17/83 AJH changed gotStrike to FF instead of 01 cause of Bill A.
; 3/7/83 AJH excluded font 0 in RealFont; added ScaleDisable
; 3/6/83 AJH Added support for strike-less FWID resource
; 3/5/83 AJH Changed way numer/denom is computed to avoid overflow
; 2/27/83 AJH Fixed bug making font 1 not work
; 2/25/83 AJH Made GetFID divide result by 64
; 2/16/83 AJH Got rid of the ROM-based font, added RealFont function
;
; ———————————————————————————————————————————————————————————————————————————————————
BLANKS ON
STRING ASIS
;——————————————————————————————————————————————————————————————————————————————————————————
; Check Defines…
;——————————————————————————————————————————————————————————————————————————————————————————
IF (&TYPE('HAS_COLOR') = 'UNDEFINED') THEN
HAS_COLOR EQU hasCQD
ENDIF
IF (&TYPE('forJP') = 'UNDEFINED') THEN
forJP EQU 0
ENDIF
;——————————————————————————————————————————————————————————————————————————————————————————
IF (forROM) THEN ;<2.7-4april89-CEL>
debugging EQU 0
MACRO
Check &ea,&dReg
IF debugging THEN
CHK &ea,&dReg
ENDIF
ENDM
MACRO
_Debug
IF debugging THEN
DC.W $A9FF
ENDIF
ENDM
MACHINE MC68020
ELSE
CASE OBJ
PrNonPortable EQU 1 ; Needed for patches
MACHINE MC68020
ENDIF ; <2.7-4april89-CEL>
IF (&TYPE('fmOutCurStyle') = 'UNDEFINED') THEN
PRINT OFF
IF (NOT forROM) THEN ; Using private includes for now until checked into the system <2.7-4april89-CEL>
INCLUDE 'Quickequ.a'
INCLUDE 'ColorEqu.a'
INCLUDE 'sysequ.a'
INCLUDE 'Traps.a'
INCLUDE 'ToolEqu.a'
INCLUDE 'SplineDefines.a'
INCLUDE 'ScriptEqu.a' ; <3.6>
INCLUDE 'SysPrivateEqu.a'
include 'Private.a' ; <19>
INCLUDE 'LinkedPatchMacros.a' ; <Sys7.1>
ELSE
LOAD 'StandardEqu.d' ; <C206><1.4>
INCLUDE 'ColorEqu.a'
ENDIF
INCLUDE 'fontPrivate.a'
INCLUDE 'qdhooks.a'
include 'ResourceMgrPriv.a' ; <22>
INCLUDE 'Scriptpriv.a' ; <3.6>
PRINT ON
ENDIF
; Here are the external definitions that let the font manager communicate
; with the rest of the world.
IF forROM or HAS_COLOR THEN
MakePatch InitFonts,_InitFonts,(II,IIci) ; <Sys7.1>
MakePatch SetFontLock,_SetFontLock,(II,IIci) ; <Sys7.1>
MakePatch GetFontName,_GetFName,(II,IIci) ; <Sys7.1>
MakePatch GetFNum,_GetFNum,(II,IIci) ; <Sys7.1>
MakePatch FMSwapFont,_FMSwapFont,(II,IIci) ; <Sys7.1>
MakePatch RealFont,_RealFont,(II,IIci) ; <Sys7.1>
MakePatch FontMetrics,_FontMetrics,(II,IIci) ; <Sys7.1>
FontManager PROC EXPORT
EXPORT InitFonts
EXPORT SetFontLock
EXPORT GetFontName
EXPORT GetFNum
EXPORT FMSwapFont
EXPORT RealFont
EXPORT FontMetrics
IF forROM THEN
EXPORT SetFScaleDisable
EXPORT SetFractEnable
IMPORT GetDevPix ; GetDevPix is with CQD routines in ROM
ELSE
EXPORT GetDevPix ; If not ROM build, GetDevPix in Font manager
ENDIF
EXPORT FMgrEnd
EXPORT FPointOne ; (so that first reference will be seen.)
ELSE
MakePatch BWInitFonts,_InitFonts,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWFMSwapFont,_FMSwapFont,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWGetFontName,_GetFName,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWRealFont,_RealFont,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWGetFNum,_GetFNum,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWSetFontLock,_SetFontLock,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWSetFScaleDisable,_SetFScaleDisable,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWSetFractEnable,_SetFractEnable,(Plus,SE,Portable) ; <Sys7.1>
MakePatch BWFontMetrics,_FontMetrics,(Plus,SE,Portable) ; <Sys7.1>
BWFontManager PROC EXPORT
EXPORT BWInitFonts
EXPORT BWSetFontLock
EXPORT BWGetFontName
EXPORT BWGetFNum
EXPORT BWGetDevPix
EXPORT BWFMSwapFont
EXPORT BWRealFont
EXPORT BWFontMetrics
EXPORT BWFMgrEnd
EXPORT BWFPointOne ; (so that first reference will be seen.)
EXPORT BWSetFScaleDisable
EXPORT BWSetFractEnable
ENDIF
IF NOT (&TYPE('testVersion') = 'UNDEFINED') THEN
INCLUDE 'FontMgrInstall'
ENDIF
; With Color and gray scale font support, the Font flags, FOND style word in the property association
; table, and the width table get expanded as shown:
; Font flags:
; 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
; 1 intl m/p 1 0 0 colr syn fctb 0 0 pixel-width wid height <BAL 08May88> @@@@
;
; m/p indicates whether the font is monospaced or proportional, same as always.
; intl is set if the font is an international font which should not be expanded (Kanji, for instance).
; colr is set if the font contains colors other than black and white.
; syn is set only when the font is synthetic and created on the fly with the requested bit depth.
; (should always be clear for disk fonts)
; fctb is set if the font has a color table in a resource of type fctb with the same ID as the font.
; bits 2 - 4 represent the bit depth of the describing a range of 1 to 8 bits per pixel. (0 = 1, 1 = 2, 2 = 4, 3 = 8, etc)
; wid is set if the font has a fixed-point width table.
; height is set if the font has a character height/length table appended to the end.
; style word in FOND property association table:
; 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
; 0 0 0 0 0 pixel-width | ————normal QuickDraw style byte——— <BAL 08May88> @@@@
;
; bits 8 - 10 represent the bit depth of the (0 based) describing a range of 1 to 32 bits per pixel. (0 = 1, 1 = 2, 2 = 4, 3 = 8, etc)
;——————————————————————————————————————————————————————————————————————————————————————————
; PROCEDURE InitFonts -- initialize the font manager data structures
;——————————————————————————————————————————————————————————————————————————————————————————
if forROM or HAS_COLOR then
InitFonts
else
BWInitFonts
endif
IF HAS_COLOR THEN ; FMExist does not exist on the MacPlus!!!
TST.B FMExist ; has the font manager been initialized?
BEQ @skipRest ; if flag clear, then yes
ENDIF
MOVEQ #-1,D2 ; get some ones
CLR.W FOutError ; clear once at init time
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 @doneAlloc ; Check for spline ready
MOVE.L #WidTabSize,D0 ; size of table
_NewHandle ,SYS ; new handle in sysHeap
BNE CantAllocMem ; if an error, skip <Sys7.1> Unshortened branch
MOVE.L A0,WidthTabHandle ; remember it
; allocate a width table list if there is room for them. (part of PM298 removes the next three lines)
MOVE.L #WidListSize,D0 ; size of table
_NewHandle ,SYS,CLEAR ; new handle in sysHeap, cleared
BNE.S @doneAlloc ; Check for spline ready
MOVE.L A0,WidthListHand ; remember it
@doneAlloc
BCLR #preserveGlyph, HiliteMode ; Do not always blit everything unless set
BCLR #splinePreferred, HiliteMode ; Set to bitmap preferred
; Invalidate all of the extra width tables, if they exist.
; set up swapFont jump table entry (part of PM298)
IF forROM THEN ; determine if in ROM code of if patched
MOVE.L $1204,JSwapFont ; set up the jump vector
ELSE ; if patch
MOVE #$101,D0 ;
_GetTrapAddress ;
MOVE.L A0,JSwapFont ;
ENDIF
IF HAS_COLOR THEN ; <Sys7.1> Restored conditional for 'color strike' code
MOVEQ #SyntheticStrikeTable.synEntry,D0 ; size of 1 entry version
MOVE.L SynListHandle,D1 ; already got it?
BLE.S @createSynList ; if zero or -1, create one
; mark all entries as nothing
MOVE.L D1,A0 ; existing list handle
_SetHandleSize ; restore to single entry version
BRA.S @inval1stRecord
@createSynList
_NewHandle ,SYS ; create synthetic font list with one entry
BNE.S CantAllocMem ; real trouble if no memory in application zone
MOVE.L A0,SynListHandle
@inval1stRecord
MOVE.L (A0),A0
MOVE.L D2,SyntheticStrikeTable.synNFNT(A0) ; mark first entry as invalid
@makeSysFont
TST.B fmExist
BPL.S @skipRest
CLR.B fmExist
ENDIF ; <Sys7.1> HAS_COLOR
CLR.L FOutFontHandle ; may point to non-existent font, so clear
CLR.L LastFOND
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
IF (NOT forROM) THEN ;
With SMgrRecord ; Script Manager call out from initfonts
GetSMgrCore a0 ;
move.l sVectSMgrInitFonts(a0),a0 ;
jmp (a0) ;
EndWith ;
ELSE
IF (NOT forJP) THEN ; 32-Bit QuickDraw build?
IMPORT SMgrInitFonts ; (in file SMgrPatch.a)
BigJMP SMgrInitFonts,A0 ; Script Mgr sets sys & app fonts
ELSE ;
RTS
ENDIF ;
ENDIF ;
; 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!
CantAllocMem ;
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 ; check to see if -1
BEQ.S @skipUnintialized ; if it is don't set state
_HSetState ;
@skipUnintialized ;
; _HSetState ; wasn't testing for -1
MOVEQ #-1,D2 ; get some ones
MOVE.L D2,LastSPExtra ; flag that we can't get a match next time
MOVE.W D2,FONDID ; init FOND cache (bug fix: not specific to color)
IF (HAS_COLOR) THEN ;
; DIspose of all synthetic entries inside the synthetic strike list.
MOVE.L SynListHandle,A0
_GetHandleSize
MOVE.L (A0),A1
MOVE.L D0,D1 ; size of handle
DIVU #SyntheticStrikeTable.synEntry,D1 ; number of entries
SUBQ #1,D1 ; zero base for DBRA
@topOfLoop
MOVE.L (A1)+,A0 ; handle to strike
CMP.L (A1),D2 ; is the ID invalid?
BEQ.S @nextEntry ; if so, nothing else to do
_DisposHandle ; throw away the strike
MOVE.L D2,(A1) ; mark the entry as invalid
@nextEntry
ADD #SyntheticStrikeTable.synEntry-SyntheticStrikeTable.synNFNT,A1 ; advance past ID, colors
DBRA D1,@topOfLoop
MOVE.L SynListHandle,A0 ; get handle to list
MOVEQ #SyntheticStrikeTable.synEntry,D0 ; size of 1 entry version
_SetHandleSize ; restore to single entry version
ENDIF
MOVE.L WidthListHand,D0
BEQ.S InvalWidthTab
MOVE.L D0,A1
MOVE.L A1, A0 ; Get handle in A0 for trap <9-CEL,KON,SMC>
_HGetState ; Save state for restore <9-CEL,KON,SMC>
MOVE.B D0, -(SP) ;
_HLock ; lock for sethandlesize below <9-CEL,KON,SMC>
MOVE.L (A1),A1 ; handle->pointer
MOVEQ #NumTables-1,D1
@5 MOVE.L (A1)+,D0 ; get a handle from the table
BEQ.S @66 ; end of table. <9-CEL,KON,SMC>
MOVE.L D0,A0
MOVE.L (A0),D0 ; was this handle purged?
BEQ.S @55
MOVE.L #WidTabSize,D0 ; size of new width tablesize
_SetHandleSize ; resize the handle since it started out smaller
beq.s @getNewSize
BNE.S CantAllocMem ; We're dead, don't bother cleaning up stack
@getNewSize
MOVE.L (A0),A0
MOVE.L D2,WidTabFont(A0) ; invalidate it
MOVE.W D2,WidthFID(A0) ; and invalidate requested font ID.
SF WidthIsSpline(A0) ; Set width table to bitmap
ST WidthLoadSpline(A0) ; try loading spline
sf KeepSplineOnDisk(a0) ; try loading it into memory (assume it's less than 128k)
@55 DBRA D1,@5 ; until end of table.
@66
MOVE.L WidthListHand,A0 ; Get the handle for resetting <9-CEL,KON,SMC>
MOVE.B (SP)+, D0 ; restore state in D0 <9-CEL,KON,SMC>
_HSetState ; restore the state of handle <9-CEL,KON,SMC>
; Invalidate the width table.
InvalWidthTab
MOVEQ #-1,D2 ; set up invalid value
MOVE.L WidthTabHandle,A0 ; Get Width table Handle in A0
MOVE.L #WidTabSize,D0 ; size of new width tablesize
_SetHandleSize ; resize the handle since it started out smaller
beq.s @getNewSize1
BNE CantAllocMem ; We're dead, don't bother cleaning up stack
@getNewSize1
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
SF WidthIsSpline(A0) ; Set width table as bitmap
ST WidthLoadSpline(A0) ; try loading spline
sf KeepSplineOnDisk(a0) ; try loading spline into memory (assume it's less than 128k)
@skipSetHandle
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, dont 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
if not(forROM) then ; GetDevPix is in CQD in ROM builds
;——————————————————————————————————————————————————————————————————————————————————————————
; Moved in from BassCommTail (now part of BassPatches)
;——————————————————————————————————————————————————————————————————————————————————————————
if HAS_COLOR then
GetDevPix
else
BWGetDevPix
endif
;——————————————————————————————————————————————————————————————————————————————————————————
;
; UTILITY GetDevPix;
;
; Returns a pointer to theGDevice's pixMap in A0
;
MOVE.L theGDevice,A0 ; GET A HANDLE TO THE GRAFDEVICE
MOVE.L (A0),A0 ; GET A POINTER TO THE GRAFDEVICE
MOVE.L GDPMAP(A0),A0 ; GET HANDLE TO THE DEVICE'S PIXMAP
SHARE MOVE.L (A0),A0 ; GET PIXMAP POINTER
RTS
endif ; not forROM case
;———————————————————————————————————————————————————————————————————
SwapFontStackFrame Record 0,Decr
copyInput ds.b 16 ; A copy of CurFMInput
styleID ds.l 1 ; Saved style and ID from current FOND. (Set up in GoLoadStrike)
paramBlk ds.b ioQElSize ; Parameter block used to give the current device a chance to mess with the output record
saveMap ds.w 1 ; The applications resource map in case we need to switch resource maps
fwidStyle ds.w 1 ; Style of the best width tabel found in the FOND
if HAS_COLOR then
fPixMap ds.b pmRec ; Passed to MakeScaleTbl to return color map
foreBack ds.b 12 ; Space for current foreground/background colors
curTxMode ds.w 1 ; Current text mode, used when deciding proper fore/back colors
endif
stackFrame equ *
EndR
;
; FUNCTION FMSwapFont(inRec:FontInputRecord):^FontOutputRecord
;
; 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.
;
if forROM or HAS_COLOR then
FMSwapFont
else
BWFMSwapFont
endif
; If no width table, initialise Font Manager for Gaudi.
With SwapFontStackFrame
tst.l widthTabHandle
bne.s @hasWidthTable
movem.l a0-a2/d0-d3,-(sp)
_InitFonts
movem.l (sp)+,a0-a2/d0-d3
@hasWidthTable
; Check FontFlag to see if we got here through SysError first.
; Need to save the family id of the last swapfont call since the FontMgr
; sets CurFMFamily to -1 when a widthtable is purged. The family id is used
; in the BassCache code to determine which script the current font is mapped
; to. The script is then used to lookup the correct cmap, etc.
move.l expandMem,a0 ; get low memory global
move.l ExpandMemRec.emSplineKey(a0),a0 ; get handle to splinekey
move.l (a0),a0 ; get pointer to spline key
move.l 4(sp),a1 ; get input record address
move.w fmInFamily(a1),splineKeyRec.fLastSwapFontFamilyID(a0) ; save family id for BassCache code.
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
_Debug
BSR InvalWidthTab ; dont 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 didnt 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 FamSizeInD0 ; returns family, size
MOVE.L D0,D2 ; save input record, substituted
LEA CurFMInput,A3 ; maybe actuals need subbing as well
BSR FamSizeInD0 ; get last family, size
MOVE.L (SP)+,A3 ; restore
CMP.L D2,D0 ; the same?
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
BNE DifFont
ELSE
BNE.S GoDifFont
ENDIF
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, dont check space extra
MOVE.L D0,A0
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
MOVE txMode(A0),D1
CMP LastMode,D1
BNE.S GoDifStyle
; I also need to check to see if the foreground or background color has changed !
LEA fgColor(A0),A1
LEA LastFore,A0
CMPM.L (A0)+,(A1)+
BNE.S GoDifStyle
CMPM.L (A0)+,(A1)+
BNE.S GoDifStyle
MOVE.L D0,A0
; check the bit depth of the port
BSR GetPixDepth
CMP LastDepth,D0
GoDifStyle
BNE DifStyle
MOVE.L ([grafGlobals,A5],thePort),A0 ; re-set up thePort
ENDIF
@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 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 WidthTabHandle, A1
MOVE.L (A1), A1 ; Width table ptr
TST.B WidthIsSpline(A1) ; Get flag stating if spline <14-jlf>
beq @DoNormalPurgeCheck ; do normal stuff if not a spline <14-jlf> <Sys7.1> Unshortened branch
tst.b KeepSplineOnDisk(a1) ; should we do the load? <14-jlf>
bne @skipBuildTable ; no, skip it <14-jlf> <Sys7.1> Unshortened branch
move.w WidthStrikeID(a1),d0 ; setup sfnt resource id parameter <14-jlf>
jsr LoadSplineFontResource ; load the spline font resource <14-jlf>
bsr DerefWidthTab ; get the widthtablepointer in a0 <14-jlf>
move.l a0,a1 ; save widthPointer <14-jlf>
move.l d0,a0 ; move splineHandle <14-jlf>
tst.l (a0) ; was the spline loaded? <14-jlf>
seq KeepSplineOnDisk(a1) ; no, don't try to load it again. <14-jlf>
bra @skipBuildTable ; Do not build height table if spline <14-jlf> <Sys7.1> Unshortened branch
@DoNormalPurgeCheck
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
@skipBuildTable
; all done with FMSwapFont so restore registers and return to our caller
FMSwapDone
BSR DerefWidthTab ; get pointer to width table in A0
TST.B WidthIsSpline(A0) ; Test if spline
BEQ @skipSpline ; not a spline <Sys7.1> Unshortened branch
MOVEM.L A0-A1/D0-D2,-(SP) ; Save regs
SUBQ #4,SP ; make room for result
MOVE.L WidthTabHandle, -(SP) ; 1) Push the Width Table Handle onto the stack
_sbSearchForCache ; Call the routine via SplineDispatch
TST.L (SP)+ ; check for errors
MOVEM.L (SP)+, A0-A1/D0-D2 ; Restore regs
BNE.S @skipSpline ; bail
MOVE.L expandMem, A0 ; get low mem expand
MOVE.L ExpandMemRec.emSplineKey(A0), A0 ; get handle to splineKey
MOVE.L (A0), A0 ; pointer to splinekey
MOVE.L splineKeyRec.cacheHand(A0), A0 ; is there a cache
MOVE.L (A0), A0 ; pointer to the cache
LEA cache.fmAscent(A0), A0
LEA FOutAscent, A1 ;
MOVE.B (A0)+,(A1)+ ; copy ascent
MOVE.B (A0)+,(A1)+ ; copy descent
MOVE.B (A0)+,(A1)+ ; copy widMax
MOVE.B (A0),(A1)+ ; copy leading
ADDQ #1, A1 ; bump to numer passed unused
MOVE.L #$01000100, (A1)+ ; fill in numer for splines always 1,1
MOVE.L #$01000100, (A1) ; fill in denom for splines always 1,1
@skipSpline
; 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.
@cleanUp
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
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
;————————————————————————————————————————————————————————————————————
; 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)
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
;—————————————————————————————————————————————————————————————————
PurgeOnTheFly
; see if last font supplied was synthesized font. if so, make it purgable
CMP #-1,FONDID
BEQ.S @nothingToDo
MOVE.L FOutFontHandle,D0 ; does it exist at all?
BEQ.S @nothingToDo ; wont exist at InitFonts time
MOVE.L D0,A0 ; pointer to font
MOVE.L (A0),D0 ; did it purge?
BEQ.S @nothingToDo
MOVE.L D0,A1
BTST #0,(A1) ; is it an on-the-fly font?
BEQ.S @nothingToDo
_HPurge ; make it purgable
@nothingToDo
RTS
ENDIF
;———————————————————————————————————————————————————————————————————
; 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
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
BSR.S PurgeOnTheFly
ENDIF
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.
;
; 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 isnt a nonpurged entry then were out of luck; dont use cache.
; if a memory allocation call fails, then the system heap is in bad shape; dont 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 ; dont 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 <1.7/22mar89>
_HNoPurge ; Make the Width Table non-purgeable <1.7/22mar89>
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 <1.7/22mar89>
MOVE.L (A4), A4 ; Pointer to Width Table Handles <1.7/22mar89>
ADD D5, A4 ; Add Offset of current Width Table <1.7/22mar89>
MOVE.L (A4), A1 ; Handle to Width Table <1.7/22mar89>
MOVE.L (A1), A1 ; Width Table ptr <1.7/22mar89>
LEA WidthUsedFam(A1),A1 ; Load the address of the WidthUsedFam <1.7/22mar89>
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.
_MaxBlock ,SYS ; better than FreeMem; unfortunately, didnt know for Aladdin ROM
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.
; <57> The width table should always be allocated in the system heap. However, ReAllocHandle
; is stupid, and will allocate the memory in the current heap, so set the current zone
; to be the system zone to ensure system heap allocation.
move.l TheZone,-(sp) ; <57> Save the current zone
move.l SysZone,TheZone ; <57> Make the system zone the current zone
_ReAllocHandle ; so that the memory for the width table will always be
move.l (sp)+,TheZone ; <57> allocated in the system heap.
tst.w d0 ; <62> Refresh the result code.
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 ; dont 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 WidthTabHandle, A1
MOVE.L (A1), A1 ; get Width Table pointer <14-jlf>
TST.B WidthIsSpline(A1) ; is this a spline width table? <14-jlf>
beq @SkipSplineLoad ; no, do non-spline cases <14-jlf> <Sys7.1> Unshortened branch
tst.b KeepSplineOnDisk(a1) ; should we load the spline? <14-jlf>
bne NoColors ; no, skip the load <14-jlf>
move.w WidthStrikeID(a1),d0 ; setup sfnt resource id parameter <14-jlf>
jsr LoadSplineFontResource ; load the spline font resource <14-jlf>
bsr DerefWidthTab ; get widthPointer in a0 <14-jlf>
move.l a0,a1 ; save widthPointer <14-jlf>
move.l d0,a0 ; load spline handle into a0 <14-jlf>
tst.l (a0) ; was the spline loaded? <14-jlf>
seq KeepSplineOnDisk(a1) ; no, don't try to load it next time <14-jlf>
bra NoColors ; Splines do not expand whole strike on the fly <14-jlf>
@SkipSplineLoad
MOVE.L FOutFontHandle,A0 ; get the current font handle <14-jlf>
BSR DeRefResource ; load resource who's handle is in A0. <14-jlf>
; 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 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
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
BRA.S DoStyle
;—————————————————————————————————————————————————————————————————————————————
; GetPixelDepth returns the size in bits of a destination pixel in D0.
; GetPixDepth is an alternate entry used by the start of FMSwapFont to see if the destination depth has changed.
; uses D0, A0, A1
;
GetPixelDepth
TST.B QDExist ; is QuickDraw around
BMI.S useDefault
GetPixDepth
MOVE.L grafGlobals(A5),A1
MOVE.L thePort(A1),D0
BEQ.S useDefault ; no port after InitGraf until at least InitWindows (and InitFonts in between!)
MOVE.L D0,A0
; This code used to dig ScrnBase out of the QuickDraw Globals. <SM22>
; This doesn't work so well because Cyclone changes ScrnBase on depth switch <SM22>
; without updating the QuickDraw Globals. A "More Correct" fix would be to <SM22>
; have the process manager update the QuickDraw Globals of all running processes. <SM22>
MOVE.L screenBits(A1),D0 ; get pointer to screen base address <SM22> <Sys7.1> Reverted the change described
TST portBits+rowBytes(A0) ; IS SRC A PIXMAP?
BPL.S @doBits ; =>NO, IT'S A BITMAP
MOVE.L ([portBits+baseAddr,A0]),A0 ; GET POINTER TO PORT'S PIXMAP
CMP.L pBaseAddr(A0),D0 ; does pixelmap point to the screen?
BEQ.S @useDevDepth ; if so, use the gDevice depth
BRA.S @usePixDepth ; if not, use the pixel map depth
@doBits
CMP.L portBits+baseAddr(A0),D0 ; IS BITMAP BASEADDR SAME ?
BNE.S useDefault ; if offscreen and old port must be 1 deep
@useDevDepth
bsr.l GetDevPix ; bitmap points to screen, so get screen depth <BAL 09May88> @@@@
@usePixDepth
MOVEQ #0,D0 ; zero high word
MOVE pixelSize(A0),D0 ; get the bit depth (zero flag clear)
RTS
useDefault
MOVEQ #1,D0 ; assume old style bit maps are always 1 deep (zero flag clear)
RTS
;———————————————————————————————————————————————————————————————————
DifStyle
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.
BSR PurgeOnTheFly
BSR DerefWidthTab ; pointer to width table.
MOVE.L WidTabFont(A0),A0 ; corresponding font handle.
MOVE.L A0,FOutFontHandle ; set the font handle to the original 1 bit guy for expansion
ENDIF ; END colorgrayness
DoStyle
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
; If the destination depth is 1, or if QuickDraw must algorithmically add a style, or if there is less than 3K of stack left,
; or if the international bit is set in the font, dont look for a color font.
BSR.S GetPixelDepth ; the depth of the destination bitmap
MOVE.L D0,D6 ; the device pixel size
CMP #1,D6 ; 1 bit?
BEQ.S @noColors
MOVE.B FOutCurStyle,D0
AND.B #$9F,D0 ; turn off condense, extend
BNE.S @noColors ; are there algorithmic additions?
_StackSpace
CMP.L #$0C00,D0 ; at least 3K of stack?
BLT.S @noColors ; if not, use 1 bit font
bsr DerefWidthTab ; dereference the width table <14-jlf>
tst.b WidthIsSpline(a0) ; is this a spline font? <14-jlf>
bne NoColors ; yes, skip this color madness <14-jlf>
MOVE.L FOutFontHandle,A0
BSR DeRefResource ; make sure it is loadable
BTST #6,(A0) ; test international bit
BEQ.S LookForColor ; if clear, it is OK to expand
@noColors
toNoColors ; label referenced below
BRA NoColors
;———————————————————————————————————————————————————————————————————
; LookForColor scans the table of synthesized color fonts looking for a match. It is passed the resource
; ID of the strike to find, and a hint of where the last one was found.
; It sets the Z condition flag if a match is found.
;———————————————————————————————————————————————————————————————————
LookForColor
BFFFO D6{$1A,6},D6 ; turns 32, 16, 8, 4, 2, 1 into $1A, $1B, $1C, $1D, $1E, $1F <BAL 08May88> @@@@
NOT D6 ; $FFE5 … $FFE0
AND #7,D6 ; 5, 4, 3, 2, 1, 0 (amount to shift to multiply by bit depth) <BAL 08May88> @@@@
; get the foreground and background colors, if needed
MOVE #1,curTxMode(A6) ; assume text mode is srcOr
LEA foreBack(A6),A1 ; set foreground to default of black
CLR.L (A1)+ ; clear the foreground r, g
CLR.W (A1)+ ; clear the foreground b
MOVEQ #-1,D0 ; full intensity
MOVE.L D0,(A1)+ ; set the background r, g
MOVE.W D0,(A1) ; set the background b
; 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 @useDefault
MOVE.L ([grafGlobals,A5],thePort),D0 ; get the port
BEQ.S @useDefault ; no port after InitGraf until at least InitWindows (and InitFonts in between!)
MOVE.L D0,A0
MOVE txMode(A0),D0
AND #$FFF7,D0 ; clear the pattern bit, in case it was set by the user by mistake
MOVE D0,curTxMode(A6)
CMP #$32,D0 ; hilite?
BEQ.S toNoColors ; if so, return 1 bit font
BCLR #5,D0 ; arithmetic mode?
BNE.S @arithMode ; if not, use black and white
BCLR #2,D0 ; a “not” mode? (we ignore these now and create synth font) <5JUNE92 SAH>
SUBQ #srcBic,D0 ; srcBic?
BEQ.S toNoColors ; if so, return 1 bit font
BRA.S @useDefault ; multibit font, but black/white
@arithMode ; <5JUNE92 SAH>
; Here is Shannon's changes to text to make it draw faster!
; The code currently uses the arithmetic mode bit (bit 5) to mean color font. It passes this
; to MakeScaleTbl to get it to colorize. The only problem is that MakeScaleTbl uses bit 3
; to determine if it needs to colorize, so no colorizing happens. When creating a synthetic
; font, this code checks bit 5. If it's set, it marks the font as color (because MakeScaleTbl should
; have colorized it). When calling stretch, it passes multColor to be true if the font is color.
; This means that when a synthetic font is created and an arithmetic transfer mode is set, multColor is set
; to true in StretchBits, even though the source is entirely black and white. It also means that color
; fonts are not colorized.
; It is stupid to use bit 5 for colorizing as it doesn't do this.
; It is also stupid to mark synthetic fonts as color when they're not.
; for now, I'm going to clear bit 5 in the curTxMode (here) and create a B&W font. This means
; that we can change the meaning of multColor in stretch to be a bit field, where bit 0 means
; that the source is entirely black and white. Therefore, we can take BitBlt rather than
; ScaleBlt.
BCLR #5,curTxMode + 1(A6) ; clear arithmetic mode <5JUNE92 SAH>
bra.s @useDefault ; <5JUNE92 SAH>
@useColor ; multibit font, fg/bg colors
PEA foreBack(A6)
_GetForeColor
PEA foreBack+6(A6) ; for srcCopy use normal forground, background
_GetBackColor
@useDefault
MOVE.L A3,-(SP) ; preserve register
move.w CurMap,-(sp) ; <29> Save current resource map, outside of some major spaghetti code
;———————————————————————————————————————————————————————————————————
; look for a multibit font, if it is around
MOVEQ #0,D3 ; assume no multibit font on disk
MOVEQ #0,D5 ; assume no second best match
MOVE D6,D7 ; if we do find a multibit font, assume it is an exact (depth) match
MOVE D6,D0
ASL #8,D0 ; shift to high byte
OR.B fmInFace(A3),D0 ; add in actual style requested
MOVE.B FOutCurStyle,D1 ; could be condense, extend
EOR.B D1,D0 ; if so, turn them off
BSR DerefWidthTab
MOVE widthASize(A0),D2 ; actual size font returned
; scan through FOND looking for matching size and style
MOVE.L LastFOND,D1 ; is there a FOND?
BEQ @noEntry ; if not, no preexpanded fonts
move.l ExpandMem,a0 ; <29>
move.l ExpandMemRec.emSplineKey(a0),a0 ; <29> Get pointer to TrueType variables
move.l (a0),a0 ; <32>
move.w splineKeyRec.lastFontMap(a0),CurMap ; <29> Set up resource map that last font was fetched from
MOVE.L D1,A0 ; if so, check it for fast fonts
MOVE.L (A0),A0
LEA FontFamilyRecord.FONDAssoc(A0),A0 ; skip header
MOVE.W (A0)+,D1 ; fetch # of entries
@FTSLoop
CMP.W (A0)+,D2 ; search for matching size
BLT.S @secondBest ; sizes must be in ascending order
BNE.S @skipStyle ; if the style is too small, dont check the style
CMP.W (A0),D0 ; is the style high-byte (bit depth) equal to the request?
BEQ.S @foundEntry
; also look for a smaller bit depth than the one requested if an exact match is not found. Keep it around just in case
; dont worry about 1 bit; it has already been found. And it cant be 8 bit (depth = 3), since that would already be an
; exact match.
; FONDs containing more than 1 font in different depths should order the entries in bitdepth ascending order so that the
; second guess will be the deepest font. As an example, if a FOND contained a 2 bit font followed by a 4 bit font,
; the 4 bit font is chosen if the destination is 8 bits. (Of course, the 1 bit font would be chosen in the 1 bit destination case,
; the 2 in the 2 bit dest. case, and the 4 in the 4 bit dest. case.)
MOVE.W (A0),D4 ; get the style word
CMP #$0100,D4 ; is it 1 bit?
BLT.S @skipStyle
@bumpStyle
CMP #$0500,D4 ; is it 32 bit? <BAL 08May88> @@@@ used to be 0300
BGE.S @skipStyle
ADD #$0100,D4 ; bump the bit depth
CMP D4,D0 ; does the bumped depth match the request?
BNE.S @bumpStyle
MOVE.L A0,D5 ; save the second best
@skipStyle
ADDQ #FAssocSiz-2,A0
DBRA D1,@FTSLoop
@secondBest
TST.L D5 ; a less precision multi-bit font around?
BEQ.S @noEntry
MOVE.L D5,A0 ; if so, point to it
MOVE.B (A0),D7 ; and set up the depth
@foundEntry
MOVE 2(A0),D0 ; get strike ID
MOVE D0,D5 ; save a copy for later
BSR LoadNoROM ; try to load it from system first
BNE.S @gotOne
; only look in ROM if FOutFontHandle is also in ROM
MOVE.L FOutFontHandle,A0 ; could be a 1 bit ROM font
BSR DerefResource ; get a pointer to it
MOVE.L A0,D0
_StripAddress ; but only look at the valid part of the address
MOVE.L D0,A0
MOVE.L ROMBase,D0 ; do the same to the ROM base pointer
_StripAddress
CMP.L D0,A0 ; is it below the ROM?
BLT.S @noEntry ; if so, skip looking for a expanded font in the ROM
MOVE D5,D0
BSR LoadNewStrike ; then look in ROM
BEQ.S @noEntry
@gotOne
MOVE.L A0,FOutFontHandle ; install the font handle
MOVE.L A0,A2 ; set up font handle for adding to syn list
BSR BuildCharTable ; make the character (height) table
MOVE.L (A2),A0 ; get pointer to font data
CMP D6,D7 ; exact match or second best?
BNE.S @expand ; if not exact match, must map into correct depth
BTST #1,(A0) ; if colr bit is clear, install directly in the color table
BEQ SaveFont
@expand
; font can contain color, so set up the colors for makescaletbl
BCLR #5,curTxMode+1(A6) ; start out with the bit clear
CMP #srcXor,curTxMode(A6) ; is it srcXor?
BEQ.S @skipColor ; if so, dont color it
PEA foreBack(A6)
_GetForeColor
PEA foreBack+6(A6) ; for srcCopy use normal forground, background
_GetBackColor
BSET #5,curTxMode+1(A6) ; set bit so that MakeScaleTbl will use fg, bg colors
@skipColor
@noEntry
; search through the synthesized strike table for matching colors and depth
; determine the original ID from the width table
BSR DerefWidthTab
MOVE.L widthNFNT(A0),D5 ; the strike ID
@noFontFamily
MOVE.L SynListHandle,A0
_GetHandleSize
DIVU #SyntheticStrikeTable.synEntry,D0
SUBQ #1,D0 ; number of entries, zero based
MOVE.L (A0),A0
@nextCEntry
MOVE.L (A0)+,A2 ; get the strike handle
MOVE.L (A0)+,D2 ; and the strike ID & FONT/NFNT flag
CMP.L D5,D2 ; see if it matches
BNE.S @skipToNext
TST.L (A2) ; has it been purged?
BEQ.S @skipToNext
MOVE.L (A2),A3 ; dereference
MOVE (A3),D2 ; get font flags
LSR #2,D2 ; toss height and width table bits
AND #$7,D2 ; look at only depth bits <BAL 08May88> @@@@ used to be #3
CMP D6,D2 ; same as screen depth?
BNE.S @skipToNext
MOVE.L A0,A3
LEA foreBack(A6),A1
MOVEQ #(RGBColor/2)-1,D4 ; number of longs of color, zero based
@checkNext
CMPM.L (A3)+,(A1)+
DBNE D4,@checkNext
BNE.S @skipToNext
; if it is a synthetic font, dont let it purge, since it can not be reloaded with LoadResource
MOVE.L (A2),A0
BTST #0,(A0) ; synthetic?
BEQ.S @skipNoPurge
MOVE.L A2,A0
_HNoPurge
@skipNoPurge
BRA saveFont ; take short branch out of here.
@skipToNext
ADD #SyntheticStrikeTable.synEntry-SyntheticStrikeTable.synFGColor,A0 ; skip 12 bytes color
DBRA D0,@nextCEntry
;————————————————————————————————————————————————————————————————————
; Registers used by color strike part:
; D0 = scratch D1 = scratch D2 = scratch D3 = input pixel size
; D4 = D5 = color table handle D6 = output pixel size D7 = font purge state, scratch
; A0 = scratch A1 = scratch A2 = new font A3 = save stack
;————————————————————————————————————————————————————————————————————
; Here either the source or destination bitmap or both are not one deep.
; If either the screen depth or font depth is greater than 1, then let PatConvert expand, compress, or map
; the strike. Make the font strike nonpurgable for QD routine. Then, see if the font has a color table:
MOVE.L FOutFontHandle,A0 ; get handle again
_HGetState ; need to preserve current purgability
MOVE D0,D7 ; save old state
_HNoPurge ; make nonpurgable for QD patConvert
MOVE.L (A0),A0 ; deref. it
MOVEQ #0,D5 ; assume that no color table exists
TST.B 1(A0) ; test the color table bit
BPL.S @relativeColor ; derive color table from foreground/background
; If one exists, get the resource ID from the current width table. (The resource ID of the FCLR is the same
; as the ID of the strike.) Note that only NFNTs can be color, since both a FONT and an NFNT could have the
; same ID.
BSR DerefWidthTab ; get pointer to width table in A0
MOVE.L widthNFNT(A0),D0 ; get resource ID in low word, NFNT bit in high word
BPL.S @relativeColor ; if FONT, skip trying for color table
SUBQ #4,SP ; make space for function result
MOVE.L #'fctb',-(SP) ; pass resource type
MOVE D0,-(SP) ; pass resource ID
; MOVE.W #MapTrue,RomMapInsert ; look in ROM first <SM19> rb <Sys7.1> Don't!
_GetResource ; only uses D0,A0
MOVE.L (SP)+,D5 ; if it fails, then no color table to pass to MakeScaleTbl
@relativeColor
MOVE.L D5,fPixMap+pmTable(A6) ; set up color table, if any
; save the stack so we know how much to pop after MakeScaleTbl has done its thing
MOVE.L SP,A3 ; save stack pointer
MOVE.L FOutFontHandle,A0 ; source strike
; Calc total size of the dst and set the size of patXData
MOVE.L (A0),A1 ; Ptr to font <CEL-16>
MOVE.W fFontType(A1),D0 ; Need source bit depth <10-CEL>
MOVE.W D0, D3 ; make a copy, for D3 setup <10-CEL>
LSR #2,D3 ; toss bottom two bits <CEL-16>
AND #$7,D3 ; 0 … 5 (bit depth of 1 … 32) <CEL-16>
cmp #3,d6 ; is output depth <= 8 bits/pixel? <CEL-17>
ble.s @depthOK ; use the original font <CEL-17>
tst D3 ; is the input depth only 1-bit? <10-CEL>
BEQ giveup1 ; dont scale to 16 or 32 bit. <10-CEL>
BTST #9,D0 ; does the strike contain color? <10-CEL>
BEQ giveup1 ; no, just ignore it. <10-CEL>
MOVE.W #3, D6 ; pin at 8 bit/pixel <10-CEL>
@depthOK
_GetHandleSize ; size of the original handle
MOVE.L (A0),A1 ; dereference handle <BAL/JDB 07Jul88>
MOVE fRowWords(A1),D1 ; loc table is just after strike "
ADD D1,D1 ; strike width in bytes is rowWords * 2
MULU fFRectHeight(A1),D1 ; figure size of original strike
MOVE.L D1,D5 ; remember size of strike in pixels
ASL.L D3,D1 ; scale up for bit depth
MOVE.L D1,D4 ; remember source strike size
SUB.L D1,D0 ; difference of original strike and rest of font
MOVE.L D0,D2 ; remember size of post-strike table + header
LSL.L D6,D5 ; size of destination strike in bits
ADD.L D5,D0 ; size of new font
MOVE.L FOutFontHandle,A0 ; source strike "
move.l d0,a2 ; save requested size in a2 <10-CEL><BAL/JDB 07Jul88>
move.l d2,-(sp) ; save d2 across call
_HandToHand
move.l (sp)+,d2 ; restore for later
TST D0
BNE giveUp1
move.l a2,d0
add.l #$1000, d0 ; add for slop then shrink later <10-CEL>
_SetHandleSize
BNE giveUp
move.l a2,d0 ; shrink to real size <10-CEL>
_SetHandleSize ; <10-CEL>
BNE giveUp ; <10-CEL>
MOVE.L A0,A2 ; save handle to new font <10-CEL>
MOVE.L FOutFontHandle,A0
MOVE D7,D0
_HSetState ; restore purgability of original strike
MOVE.L (A2),A1 ; dereference new handle
; fix up the flag words
MOVE D6,D0 ; get the bit depth (0 … 3)
ASL #2,D0 ; make room for the height and width bits
BSET #8,D0 ; set synthetic font bit
MOVE curTxMode(A6),D1 ; get mode word
AND #$20,D1 ; isolate arithmetic mode bit
LSL #4,D1 ; move to bit 9 (set if font contains color)
OR D1,D0 ; combine with depth
AND #$FFe3,(A1) ; clear existing depth bits <BAL 08May88> used to be fff3
OR D0,(A1) ; and save it in the font.
; There are two methods of finding the location table, either by looking just past the strike or just before the
; offset/width table. So, it is not enough to just scale owTLoc; the locTable length may not be an even multiple
; of the scale factor. To find the offset/width table, the high word of owTLoc is stored in nDescent, a field
; left over from Xerox days that doesnt appear to be in use. Assuming that fNDescent always has a negative
; value from its old use, there is no confusing it with the actual fNDescent.
MOVE fNDescent(A1),D0 ; if the original font is bigger than 128K, get the high word
SWAP D0 ; put it in its place
BPL.S @skipZero
MOVEQ #0,D0 ; zero high word
@skipZero
MOVE fOWTLoc(A1),D0 ; get the original offset
ADD.L D0,D0 ; make it bytes
SUB.L D4,D0 ; remove original strike size
ADD.L D5,D0 ; add in new strike size
ASR.L #1,D0 ; make back into words
MOVE D0,fOWTLoc(A1) ; save low word in original location in bytes
SWAP D0
MOVE D0,fNDescent(A1) ; save high word in new strike as well.
MOVEQ #$1A,D0 ; size of header
MOVE.L (A0),A0 ; pointer to original font
ADD.L D4,A0 ; size of original strike
ADD.L D0,A0 ; plus header to point to post-strike table
ADD.L D5,A1 ; offset to end of new strike
ADD.L D0,A1 ; dont forget header size
SUB.L D0,D2 ; take out header from size of post-strike tables
MOVE.L D2,D0
_BlockMove ; move tables after the strike
; put pixel size in stack record for MakeScaleTbl
MOVEQ #1,D4
LSL D3,D4 ; turn 0 … 5 into 1 … 32 <BAL 08May88> @@@@
MOVE D4,fPixMap+pixelSize(A6) ; set up bit depth
PEA fPixMap(A6) ; pass pointer to colors, or 0 if none
MOVE curTxMode(A6),-(SP) ; pass text mode
_MakeScaleTbl
; For each pixel, translate and write out
MOVE.L FOutFontHandle,A0 ; point to the source font
BSR DerefResource ; get the data handle (and re-load it if it purged)
MOVE fRowWords(A0),D2 ; nonscaled pixel width of font in words
MULU fFRectHeight(A0),D2 ; get strike height, let that be rectangle bottom
ASL.L #4,D2 ; convert words to bits
ADD #$1A,A0 ; advance past header
MOVE.L (A2),A1 ; point to the dest data
ADD #$1A,A1 ; move past header in a font
MOVEQ #1,D5
LSL D6,D5 ; translate into destination depth (1 … 32) <BAL 08May88> @@@@
MOVEQ #0,D6 ; position to start of src scan
MOVEQ #0,D3 ; position to start of dst
IF (NOT forROM) THEN ; <2.7-4april89-CEL>
BSR getIs32Bit ; 32-bit QuickDraw around?
BNE.S @nxtPixel ; if so work with longs
@nxtPixel2 BFEXTU (A0){D6:D4},D0 ; extract a source pixel
MOVE 0(SP,D0*2),D0 ; translate it
BFINS D0,(A1){D3:D5} ; and put to dst
ADD.L D4,D6 ; bump to next src pixel
ADD.L D5,D3 ; bump to next dst pixel
SUBQ.L #1,D2
BHI.S @nxtPixel2
BRA.S @afterPixelLoop
ENDIF
@nxtPixel BFEXTU (A0){D6:D4},D0 ; extract a source pixel
move.l 0(SP,D0*4),D0 ; translate it <BAL 09May88> @@@@
BFINS D0,(A1){D3:D5} ; and put to dst
ADD.L D4,D6 ; bump to next src pixel
ADD.L D5,D3 ; bump to next dst pixel
SUBQ.L #1,D2
BHI.S @nxtPixel
IF (NOT forROM) THEN ; <2.7-4april89-CEL>
@afterPixelLoop
ENDIF
MOVE.L A3,SP ; restore stack
; Almost made it. Now, install this brand new font in the synthetic strike cache and in low memory:
; if cant grow cache, just reuse old element
AddToSynList
MOVE.L SynListHandle,A0
_GetHandleSize
MOVE.L D0,D1
DIVU #SyntheticStrikeTable.synEntry,D1
SUBQ #1,D1 ; make zero based
MOVE.L (A0),A1
MOVEQ #-1,D2 ; for compare
BRA.S @skipAdvance ; skip advance first time through
@nextOne
ADD #SyntheticStrikeTable.synEntry,A1 ; advance to next entry
@skipAdvance
MOVE.L (A1),A3 ; last entry
CMP.L 4(A1),D2 ; check ID field
BEQ.S @neverUsed ; if minus one, there is no handle
TST.L (A3) ; purged?
DBEQ D1,@nextOne
; either a purged one was found or ran out of list
BEQ.S @entryPurged ; if a purged one, reuse it
; ran out of entries, so try to grow list
MOVE D0,D3 ; save old size
ADD #SyntheticStrikeTable.synEntry,D0 ;(never could grow over 64K?)
_SetHandleSize
BNE.S @entryPurged ; couldnt grow, so reuse one (practically never happen)
MOVE.L (A0),A1
ADD D3,A1 ; figure where new entry is
BRA.S @neverUsed ; fill in new entry
@entryPurged
MOVE.L (A1),A0 ; throw away old purged master pointer
_DisposHandle
@neverUsed
MOVE.L A2,(A1)+ ; save the newly created font
BSR DerefWidthTab ; get pointer to width table in A0
MOVE.L widthNFNT(A0),(A1)+ ; save the font ID, NFNT flag
LEA foreBack(A6),A0
MOVEQ #rgbColor*2,D0 ; size of foreground, background colors
_BlockMove ; move foreground, background
; new font should only be made purgable at next DifFont time
; this means FontMgr needs to know that it was a “synthetic” font via font flag
;——————————————————————————————————————————————————————————————
; putting the new strike in FOutFontHandle is enough to set it up
SaveFont
MOVE.L A2,FOutFontHandle
BRA.S restoreRegs ; all done
; the call to SetHandleSize failed, so throw away the new handle
giveUp
_DisposHandle
; the call to HandToHand failed, but make the original font purgable
giveUp1
MOVE.L FOutFontHandle,A0
MOVE D7,D0
_HSetState ; restore purgability of the strike (could be multibit)
BSR DerefWidthTab ; pointer to width table.
MOVE.L WidTabFont(A0),A0 ; corresponding font handle.
MOVE.L A0,FOutFontHandle ; set the font handle to the original 1 bit guy
restoreRegs
AlreadyCached
move.w (sp)+,CurMap ; <29> Restore current resource map
MOVE.L (SP)+,A3 ; restore pointer to input frame
ENDIF ; END ColorGrayNess
NoColors
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 cant 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 its
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 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, dont 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 FontFamilyRecord.FONDLast(A0) ; see if last character is zero.
BEQ.S MakeITab ; if so, do not calculate style here.
LEA FontFamilyRecord.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.L WidthTabHandle,A1
MOVE.L (A1),A1
TST.B WidthIsSpline(A1) ; is it a spline font
BNE.S @noStyleInWidths ; if so ignore width tables in fond and use fond property table.
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 twos 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 dont use the rounded result.
MOVE.B D0,FOutExtra ; and save the byte-sized result <BAL/NMB 07Sep88>
MakeITab ; <06Nov85>
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)
TST.B WidthIsSpline(A0) ; Get flag stating if spline <2.7-4april89-CEL>
BNE AdjustSpace ; Go to adjust space and fill width function is called
; 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
MOVE.W fNDescent(A0),D0 ; possibly the high word of owTLoc
SWAP D0 ; put it in the high word
BPL.S @notNegative
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 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
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)
@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
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
MOVE txMode(A0),lastMode
LEA fgColor(A0),A0
LEA lastFore,A2
MOVE.L (A0)+,(A2)+ ; saving the foreground/background colors for next time
MOVE.L (A0),(A2)
MOVE.L A1,-(SP)
BSR GetPixelDepth
MOVE.L (SP)+,A1
MOVE D0,lastDepth
ENDIF ; END Color GrayNess
@noQuickDraw
CLR.L D4 ; Zero out D1 for splines spExtra
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
MOVE.L D0, D4 ; SAVE Space adjustment in D1 for spline space adjustment
; 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.
TST.B WidthIsSpline(A0) ; Test if spline
BEQ @skipFill ; do not do spline things <Sys7.1> Unshortened branch
CLR.B WidthUsedFam(A0) ; Splines never used FOND widths.
tst.b KeepSplineOnDisk(a0) ; should we load the spline? <14-jlf>
bne @fontOkay ; no, skip the load. <14-jlf> <Sys7.1> Unshortened branch
move.w WidthStrikeID(a0),d0 ; push the sfnt resource id <14-jlf>
jsr LoadSplineFontResource ; load the spline resource <14-jlf>
bsr DerefWidthTab ; get widthpointer in a0 <14-jlf>
exg d0,a0 ; swap splineHandle with widthTable <14-jlf>
tst.l (a0) ; was spline loaded into memory? <14-jlf>
exg d0,a0 ; restore register positions <14-jlf>
seq KeepSplineOnDisk(a0) ; if not loaded, set flag for next time <14-jlf>
;———————————————————————————————————————————————————————————————————————————————————————————————————
; _sbFillWidthTab() ; <2.7-4april89-CEL>
@fontOkay
MOVEM.L A0-A1/D0-D2,-(SP) ; Save off all registers before JSR
SUBQ #4,SP ; make room for result
MOVE.L WidthTabHandle, -(SP) ; Push the WidthTable for updating
SUBQ #2, SP ; Make room for fractEnable
MOVE.B fractEnable, (SP) ; Get fractEnable flag
_sbFillWidthTab ; Call the routine via SplineDispatch
ADDQ #4, SP ; to late for errors <18-CEL>
MOVEM.L (SP)+, A0-A1/D0-D2 ; Restore all registers on return
BSR DerefWidthTab ; get pointer to width table in A0
ADD.L D4, 4*' '(A0) ; adjust space width
@skipFill
BSR DerefWidthTab ; get pointer to width table in A0 <8-CEL>
CLR.L 4*13(A0) ; jam carriage return to zero <8-CEL>
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
MOVE.L WidthTabHandle, A1
MOVE.L (A1), A1 ; Width table ptr
TST.B WidthIsSpline(A1) ; Get flag stating if spline
BEQ.S @notSpline ; If spline skip height and size check
SUBQ #4,SP ; make room for result
MOVE fmInSize(A3),-(SP) ; push desired size
MOVE D3,-(SP) ; push actual size
AND #$7FFF,(SP) ; make sure it is not negative - 32,768
BRA.S @contScale
@notSpline
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
@contScale
_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
if forROM or HAS_COLOR then
MOVE.L FPointOne,D1 ; set up FScaleHFact, FScaleVFact when disabled
else
move.l BWFPointOne,d1 ; <12> DTY
endif
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
_Debug
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
Check #12,D0 ; debugging aid
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 ex<73>.3 <Sys7.1> Just mask to Chicago vs calling ScriptMgr.
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
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
; Set up parameters for the screen
SetScreenDevice
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
; -------------------------------------------------------------------------------------
;
; Routine: splineHandle = LoadSplineFontResource( splineResourceID )
;
; Input: d0.w spline font resource id
;
; Output: d0.l spline font handle
;
; Purpose: Load a spline resource. If the spline resource is greater than 128k
; we load an empty resource handle into the system heap. Otherwise,
; the entire resource is loaded into the current heap. The TrueType
; scaler uses the PartialFont mechanism for fonts that are not loaded
; into memory; loading a spline into memory is for Roman performance
; improvements.
;
; Warning: None
;
; Frame: None
LoadSplineFontResourceFrame: Record {oldA6},decrement
returnAddress: ds.l 1
oldA6: ds.l 1
resourceID: ds.w 1
resourceHandle: ds.l 1
frameSize: equ *
EndR
; -------------------------------------------------------------------------------------
LoadSplineFontResource
With LoadSplineFontResourceFrame
link a6,#frameSize ; create local space
movem.l d1-d2/a0-a1,-(sp) ; save registers
move.w d0,resourceID(a6) ; save resourceID for later
move.w ResLoad,-(sp) ; <15> Save current ResLoad
move.w #0,-(sp)
_SetResLoad ; <15> Dont load the spline
move.w #MapFALSE,ROMMapInsert ; don't load sfnt into memory
subq #4,sp ; reserve space for function result
move.l #'sfnt',-(sp) ; push resource type
move.w d0,-(sp) ; push the resource id
_GetResource ; grab the resource handle
move.l (sp)+,d0 ; <15> Set the condition code properly
@foundSpline
move.l d0,resourceHandle(a6) ; pop the spline handle
beq @Exit ; bail if it was nil <Sys7.1> Unshortened branch
move.l d0,a0 ; grab the resource handle
tst.l (a0) ; is the handle already loaded into memory?
bne @Exit ; yes, return immediately <Sys7.1> Unshortened branch
; at this point the empty resource handle is:
;
; 1) newly created empty handle in the current heap.
; 2) a purged sfnt <= 128K in the system or one of several application heaps
; 3) a purged sfnt > 128K in the system heap, which means that the KeepSplineOnDisk
; flag failed and this routine shouldn't have been called.
subq #4,sp ; reserve space for function result
move.l a0,-(sp) ; push the empty resource handle
_SizeRsrc ; get the size of the resource
move.l (sp)+,d0 ; pop the resource size
cmp.l #128*1024,d0 ; is the spline size greater than 128k?
bgt @LoadEmptySplineIntoSystemHeap ; yes, load an empty spline into the system heap <Sys7.1> Unshortened branch
move.l resourceHandle(a6),-(sp) ; push empty resource handle
_LoadResource ; load the resource into memory
bra @Exit ; return <Sys7.1> Unshortened branch
; The spline font is bigger than 128K, so dont load it into memory, but create an empty
; handle for it in its resource reference entry. We can probably get rid of the call to
; ReleaseResource and the zone mucking, since its pretty unlikely for a font to be loaded
; in the application heap these days. For example, fonts from the system and the Fonts
; folder automatically load in the system heap. Fonts will go in the application heap
; if the application is carrying the font around. But at this point in the code, the
; 'sfnt' is larger than 128K, and its unlikely that applications will be carrying around
; fonts of this size. But Im too chicken to get rid of these lines at this point in
; 7.1s schedule.
@LoadEmptySplineIntoSystemHeap
move.l resourceHandle(a6),-(sp) ; push resource handle
_ReleaseResource ; get rid of empty spline from some application heap
move.w #MapFALSE,ROMMapInsert ; don't load sfnt into memory
move.l TheZone,-(sp) ; save the current zone
move.l SysZone,TheZone ; make the system heap current
subq #4,sp ; reserve space for function result
move.l #'sfnt',-(sp) ; push resource type
move.w resourceID(a6),-(sp) ; push the resource id
_GetResource ; grab the resource handle
move.l (sp)+,resourceHandle(a6) ; pop the spline handle
move.l (sp)+,TheZone ; restore the saved heap zone
@Exit
_SetResLoad ; <15> Old ResLoad is still on the stack. Restore it before we leave.
movem.l (sp)+,d1-d2/a0-a1 ; restore registers
move.l resourceHandle(a6),d0 ; set function result
unlk a6 ; destroy local space
rts ; return to caller
EndWith
; 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
BSR DerefWidthTab ; get pointer to widthtable
TST.B WidthIsSpline(A0) ; Could not load Spline so it is not Spline
BEQ.S @skipSpline ; not a spline
; d0 must contain the splinefont resource id. <14-jlf>
jsr LoadSplineFontResource ; load the spline resource handle - but, not the data <14-jlf>
tst.l d0 ; was there an error? <14-jlf>
bz.s @loadFailed ; yes, load failed so bail and try other font <14-jlf>
bsr DerefWidthTab ; get widthPointer in a0 <14-jlf>
exg d0,a0 ; swap splineHandle with widthPointer <14-jlf>
tst.l (a0) ; was the spline handle loaded into memory? <14-jlf>
exg d0,a0 ; restore register positions <14-jlf>
seq KeepSplineOnDisk(a0) ; if not loaded, set flag for next time <14-jlf>
@SkipSplineLoad
MOVEM.L A0-A1/D0-D2,-(SP) ; Save off all registers before JSR
SUBQ #4,SP ; make room for result
MOVE.L WidthTabHandle, -(SP) ; Push the WidthTable for updating
MOVE.L D0, -(SP) ; Push the fontHandle
MOVE.W #12, -(SP) ; Scan lines
MOVE.W D3, -(SP) ; ppem
_sbPreFlightFontMem ; Call the routine via SplineDispatch
TST.L (SP)+ ; Check the errors
MOVEM.L (SP)+, A0-A1/D0-D2 ; Restore all registers on return
beq.s @splineOkay
; The TrueType font couldnt be loaded for some reason. Mark width table so that the
; spline will not be loaded next time, then go find a bitmap size to use.
@loadFailed
BSR DerefWidthTab ; get pointer to widthtable
SF WidthIsSpline(A0) ; Could not load Spline so it is not Spline
SF WidthLoadSpline(A0) ; Do not try to load spline next time <29>
ADD #2,SP ; get rid of strike id
BRA FindSize ; try for the size again <29>
; Use a bitmap font instead of a TrueType font.
@skipSpline
SUBQ #4,SP ; <14-jlf>
MOVE.L #'NFNT',-(SP) ; push NFNT
MOVE.W D0,-(SP)
; MOVE.W #MapTrue,RomMapInsert ; look in ROM first <SM19> rb <Sys7.1> Don't!
_GetResource
MOVE.L (SP)+,D0 ; got it?
bz.s fontOnlyLoad ; if not, look for FONT
@splineOkay ; <2.7-4april89-CEL>
BSR DerefWidthTab ; get pointer to width table in A0
MOVE #$8000,widthNFNT(A0) ; remember that we found a NFNT
MOVE (SP)+,widthStrikeID(A0)
TST.L D0 ; clear z flag ; <3.1-16May89-CEL>
BRA weGotIt ; return z clear, handle in D0. <Sys7.1> Unshortened branch
; we couldn't find the NFNT, so look for a FONT
GetStrike
MOVE.W #MapFALSE,ROMMapInsert ; don't load the font <10 July 85>
MOVE D1,-(SP) ; pass font family
BRA.S fontOnlyNoLoad ; use common code
; This is the entry point used by OldFontLookup to get a font resource that uses the
; old numbering scheme. D3 should have the font ID on entry.
GetFontHandle
MOVE D3,-(SP) ; Save the font ID
; Load the font, looking in ROM for the font resource as well.
fontOnlyLoad
MOVE.W #MapTRUE,ROMMapInsert ; get FONT from ROM if possible <10july 85>
MOVEQ #0,D0
MOVE (SP),D0 ; Get font ID
BSR DerefWidthTab ; get pointer to width table in A0
MOVE.L D0,widthNFNT(A0) ; remember that we tried to find a FONT
; Load the font, but dont look in ROM for the resource.
fontOnlyNoLoad
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
MOVE.L (SP)+,D0 ; sets Z flag
bz.s @weDidntGetIt ; if missing, skip checking size
; But wait! What if we didnt get a font at all?
@gotFONT
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:
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 that 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.
;
; Registers on Entry:
; A2 = Family Def Handle
; D3 = Requested Size
;
; Registers used:
; A1 = Width Table Ptr
; D0 = Keeps spot of spline
; D1 = Number of font entries
; D2 = last found size in FAT
;
; Registers returned:
; A0 = Font ID
;
; CLOBBERS: …
;——————————————————————————————————————————————————————————————————
FindSize
tst.l (a2) ; See if its been purged first
bne.s @noReload
move.l a2,-(sp)
_LoadResource ; The FOND has been purged. Reload it.
@noReload
MOVE.L (A2),A0 ; handle->pointer
LEA FontFamilyRecord.FONDAssoc(A0),A0 ; bump past header
MOVE.W (A0)+,D1 ; get the # of entries
MOVE.L WidthTabHandle, A1 ;
MOVE.L (A1), A1 ; Dereference WidthTable
SF WidthIsSpline(A1) ; Mark WidthTab not spline
MOVEQ #0, D0 ; Assume no spline font
MOVEQ #0, D2 ; set size check to zero
TST.B WidthLoadSpline(A1) ; should we load the spline??? <29>
BEQ.S @fSizeLoop ; do not load spline <29>
MOVE.L A0, -(SP) ; save A0
MOVE.L expandMem, A0 ; Get low mem expand
TST.L ExpandMemRec.emSplineKey(A0) ; SplineKey is invalid?
MOVE.L (SP)+, A0 ; restore A0
BEQ.S @fSizeLoop ; yes -> cannot use spline fonts
TST.W (A0) ; First entry is spline font?
BNE.S @fSizeLoop ; no -> do normal stuff
ADDQ #2, A0 ; Increment A0 past zero size
MOVE.L A0, D0 ; save off handle of sfnt
TST.W D1 ; Any more fonts left?
BLE.S @gotSpline ; no -> done so use spline
BTST #splinePreferred,HiliteMode ; Test to see if we prefer splines
BNE.S @gotSpline ; Try for spline
BRA.S @contLoop ; Increment for next entry
@fSizeLoop
MOVE.W (A0)+, D2 ; FAT entry size
CMP.W D2, D3 ; this the one?
BEQ @getStrike ; if so, go load it (code above) <JH because of change below this can't be a short branch anymore>
BLT.S @trySpline ; if too big, too late
@contLoop
ADDQ #FAssocSiz-2,A0 ; bump to next entry
DBRA D1,@fSizeLoop ; check them all out
@trySpline
TST D0 ; check if Spline was found
BEQ.S @cantFind ; ex<SM17> <Sys7.1> Unlengthened branch
@gotSpline
;
; if Roman font, do as before
;
movem.l a1/d0-d2,-(sp) ; Save everything
clr.w -(sp)
_FontScript ; check if it's Kanji
move.w (sp)+,d0 ; get result into D0
beq.s @GoNonAsian ; moved a 0, means we are Roman font so GoNonAsian
cmp.w #smJapanese,d0 ; Japanese?
beq.s @CheckSplinePreferred ; yes, now check if spline preferred
cmp.w #smTradChinese,d0 ; not Japanese, how about traditional Chinese
beq.s @CheckSplinePreferred ; yes, check spline preferred
cmp.w #smKorean,d0 ; is it Korean
beq.s @CheckSplinePreferred ; <48> yes so check spline preferred
cmp.w #smSimpChinese,d0 ; Is it Simplified Chinese
beq.s @CheckSplinePreferred ; last time, go check spline preferred
@GoNonAsian
movem.l (sp)+, a1/d0-d2 ; Restore it all
bra.s @DoRomanLogic
;
; Use spline if spline preferred is true
;
@CheckSplinePreferred
movem.l (sp)+, a1/d0-d2 ; Restore it all
; ex<73>.1 <Sys7.1> Don't use too-small sfnt even if desparate.
btst.b #splinePreferred,HiliteMode ; bit flag set in HiliteMode?
bne.s @DoRomanLogic ; yes, force spline
;
; check if point size is big enough to use a spline for this font.
; if so, fall through and use spline.
; if not, do checkMore which uses bitmap
;
move.l d0,a0 ; get ptr to style/ID word from FOND
movem.l d0-d2,-(sp) ; Save relevent stuff
move.w #MapFALSE,ROMMapInsert ; don't load sfnt into memory
subq #6,sp ; reserve space for function result ...
move.l #'sfnt',-(sp) ; ... for GetResource and fs_LowestPPEM
move.w 2(a0),-(sp) ; push the resource id
_GetResource ; grab the resource handle
;
; leave resource handle on stack and space for result already allocated on stack
;
_fsLowestPPEM ; LOOKOUT: MOVES MEMORY!
cmp.w (sp)+, d5 ; is desired size bigger than minimum
movem.l (sp)+, d0-d2 ; Restore relevent stuff
move.l WidthTabHandle, A1 ;
move.l (A1), A1 ; Dereference WidthTable again since memory moved
blt.s @checkMore ; size is smaller than minimum spline size, branch
@DoRomanLogic
ST WidthIsSpline(A1) ; Mark width table spline
MOVE.L D0, A0 ; increment to get id
MOVE.L (A0),D0 ; get style/ID words from FOND
MOVE.B Widthface(A1), WidthAFace(A1) ; Act as if plain and get requested style
BRA.S @getStrike ; Get the sfnt strike
@cantFind
TST.W D2 ; greater size than zero???
BNE.S @checkMore ; check for more bitmap sizes
ORI #2, CCR ; set V for no resource match in FOND
RTS
@checkMore
MOVEQ #0,D0 ; z-flag set, return NIL
RTS
@getStrike
BRA GoLoadStrike ; Get the sfnt strike
;
; Candidate cache offsets
;
sizeInFOND equ 0 ; Point size described by this entry
entryStyles equ 2 ; Styles described by this entry
FONDHandle equ 4 ; 'FOND' handle containing this size and style
FONDMap equ 8 ; Resource map 'FOND' came from
kFONDListSize equ 12 ; Candidate cache entry size
;_________________________________________________________________________________________
;
; GetFONDForSizeAndStyle searches the candidate list passed in A3 for a FOND
; with the requested size and style. If the correct size and style is found,
; return a handle to the FOND in A0, and CurMap is set up to get the font out
; of the right resource file. The low word of D3 contains the desired size,
; and the high word contains the desired style on entry.
;
; GetFONDForSizeAndStyle returns a TrueType font if one is available if the requested
; size (and style) isnt available. It returns the plain style of the requested size
; if the desired style isnt available.
;
; Register Input:
; A3 -> Handle to candidate list
; D3 -> Requested Style/Requested size
;
; Register Output:
; A0 <- Best 'FOND' handle for requested size and style.
; D0 <- Non zero if candidate was found was found.
; Zero if candidate was not found.
;
; Internal register usage:
; A1 - Pointer to cache entry to use
; A4 - Current cache entry
; D2 - Size/Style comparisons
; D4 - Pointer to cache entry for styled spline
; D5 - Pointer to cache entry for styled bitmap
; D6 - Pointer to cache entry for plain bitmap
; D7 - Pointer to cache entry for plain spline
;
GetFONDForSizeAndStyle
movem.l d2-d7/a4,-(sp)
move.l (a3),a4 ; Get pointer to candidate list
addq #2,a4 ; Bump past FOND ID
move.w (a4)+,d1 ; get the # of entries in candidate list
bmi @sizeAndStyleNotFound ; <61> Dont do anything if this is an empty candidate list.
moveq #0,d2 ; Initialize size
moveq #0,d4 ; Assume no styled spline font
moveq #0,d5 ; Assume no styled bitmap
moveq #0,d6 ; Assume no plain style, either
moveq #0,d7 ; Assume no plain spline.
; For each entry in the FOND candidate list, make sure that the resource map that each
; FOND comes from is presently in the resource chain. If its not, skip the entry, and
; try another one.
@fSizeLoop
move.l d1,-(sp) ; Need to save D1 around _GetMap
subq #4,sp
move.l FONDMap(a4),a1
move.l (a1),a1
move.w mRefNum(a1),-(sp) ; Make sure the map that this FOND came from is in the resource chain
_GetMap ; Get the map handle from the reference number
tst.l (sp)+ ; If nil is returned, the map is not in the chain
bnz.s @FONDMapInChain
move.l (sp)+,d1 ; Restore D1
add.w #kFONDListSize,a4 ; The map isnt in the chain. Try the next candidate
dbra d1,@fSizeLoop
bra @CheckAlternates ; No more candidates. See if we can use something else instead.
; The resource map containing this 'FOND' is in the resource chain. Look at the font
; association table in this 'FOND' to see if it contains references to the desired
; size and style.
@FONDMapInChain
move.l (sp)+,d1 ; Restore D1
move.w (a4)+,d2 ; Get a size
bnz.s @notSpline ; This entry is not a TrueType font.
; We got a TrueType entry. Rememeber it in case a bitmap for the desired size cant be
; located.
swap d3
move.w d3,d2 ; Get the style we want
swap d3
move.w (a4)+,d0 ; Get the styles this 'FOND' describes
andi.w #$0F,d0 ; Mask off color bits
bnz.s @styledSplineEntry ; Its not plain
tst.l d7 ; <58> See if weve already remembered a plain TrueType font
bnz.s @gotPlainSpline ; <58> Weve already got one, so dont remember this new one
move.l a4,d7 ; Its plain. Remember this cache entry in case the right bitmap size isnt found.
@gotPlainSpline
tst.w d2 ; Did we want plain?
bne.s @keepLooking ; Nope. Keep looking
bra.s @checkSplinePreferred ; Yes. See if its ok to return a TrueType font.
@styledSplineEntry
; ex<71> <Sys7.1> Don't search the 'FOND' further
and.w d2,d0 ; See if this 'FOND' describes the desired style
bnz.s @savePotentialStyleMatch ; It does indeed. Prepare to load it in.
move.l d3,d0 ; <63> This 'FOND' doesnt have the desired style.
swap d0 ; <63> Check the desired style to see if were trying to get plain
tst.w d0 ; <63> If were not looking for plain, try the next candidate. Otherwise,
bnz.s @keepLooking ; <63> QuickDraw wants to use this style as plain, so remember it.
@savePotentialStyleMatch
tst.l d4 ; <58> See if we already have an alternate style
bnz.s @gotStyledSpline ; <58> <68> Weve got an alternate style already
move.l a4,d4 ; This 'FOND' has the style we want. See if we can return the TrueType font.
@gotStyledSpline
tst.w d0 ; <67> This code is used for getting a styled font. If QuickDraw really
bz.s @keepLooking ; <67> wanted a plain font, keep looking for plain.
; If splinePreferred is set, leave early if we got the right style.
@checkSplinePreferred
btst #splinePreferred,HiliteMode ; If this bit is set, it means use a TrueType font whenever possible.
bz.s @keepLooking ; Its not set. Keep looking for a bitmap of the right size.
; We want to use the TrueType font. Determine whether to return the plain or the style
tst.w d2 ; D2 still the desired style
bnz.s @passBackStyledSpline ; Return the styled variation
move.l d7,a1 ; Pass the pointer to the plain cache entry to our exit code.
bra @setupForLoad ; Go to the code which sets up the resource chain to load in the font.
@passBackStyledSpline
move.l d4,a1 ; Pass the pointer to the styled cache entry
bra @setupForLoad ; Go set up for loading the font.
; This entry in the cache is for a bitmap size. See if it matches the desired size.
@notSpline
cmp.w d2,d3 ; Correct size?
bne.s @sizeDoesntMatch ; No. Try the next entry.
swap d3
move.w d3,d2 ; Get the desired style
swap d3
move.w (a4)+,d0 ; The size is right. Check the style.
bnz.s @styledBitMapEntry
tst.l d6 ; <58> See if weve got an alternate plain bitmap
bnz.s @gotPlainBitmap ; <58> If we do, dont save this new one.
move.l a4,d6 ; Remember this cache entry as the plain base in case the desired style isnt found.
@gotPlainBitmap
tst.w d2 ; Did we want plain?
bne.s @keepLooking ; Nope. Keep looking
bra.s @checkIfBitMapIsGoodEnough
; This entry has a style. See if its the style we want.
@styledBitMapEntry
and.w d2,d0 ; See if this FOND can deal with the style we want
bnz.s @gotDesiredStyledBitMap ; It does indeed. Prepare to load it in.
move.l d3,d0 ; <63> This 'FOND' doesnt have the desired style.
swap d0 ; <63> Check the desired style to see if were trying to get plain
tst.w d0 ; <63> If were not looking for plain, try the next candidate. Otherwise,
bnz.s @keepLooking ; <63> QuickDraw wants to use this style as plain, so remember it.
@gotDesiredStyledBitMap
tst.l d5 ; <58> See if we already have a styled bitmap
bnz.s @gotStyledBitMap ; <58> <68> If we do, dont remember the new one.
move.l a4,d5 ; It has the right style. Remember this cache entry
@gotStyledBitMap
tst.w d0 ; <67> This code is used for getting a styled font. If QuickDraw really
bz.s @keepLooking ; <67> wanted a plain font, keep looking for plain.
; A bitmap of the right size and style was found. However, if splinePreferred is set, keep
; looking for a TrueType font.
@checkIfBitMapIsGoodEnough
btst #splinePreferred,HiliteMode ; See if TrueType fonts are preferred.
bnz.s @keepLooking ; Yes. Continue with the search.
; Using the bitmap font is ok. Determine which font to return (styled or plain)
tst.w d2 ; Check the desired style
bnz.s @passBackStyledBitMap ; Return styled variation
move.l d6,a1 ; Otherwise, we can return this 'FOND'.
bra.s @setupForLoad
@passBackStyledBitMap
move.l d5,a1 ; Pass pointer to styled cache entry
bra.s @setupForLoad
; At this point, either the size, style, or font type doesnt match with what we want.
; Try the next entry.
@sizeDoesntMatch
addq #2,a4 ; Skip over the style
@keepLooking
add.w #kFONDListSize-4,a4 ; bump to next entry
dbra d1,@fSizeLoop ; check them all out
;
; The entire FOND list was checked without finding a real match. See if anything else
; was picked up that can be used instead.
;
@CheckAlternates
; ex<71> <Sys7.1> Don't obey splinePreferred
tst.l d6 ; See if plain variation was found
bz.s @tryForStyledAlternate ; <67> If there is a plain, return it.
move.l d6,a1 ; The plain variant was found
bra.s @setupForLoad ; Rejoin the rest of the code
@tryForStyledAlternate
tst.l d5 ; <67> There was no plain, see if we have a style alternate
bz.s @tryForSpline ; <67> No styled bit map either. See if we have a spline.
move.l d5,a1 ; <67> Weve got a style alternate. Return that.
bra.s @setupForLoad ; <67> Return the styled bitmap.
; The plain bitmap wasnt found (either). See if a TrueType font was picked up along
; the way.
@tryForSpline
move.l d3,d0 ; Get desired style/size
swap d0 ; Get desired style in low word
tst.w d0 ; Plain or styled?
bz.s @tryForPlainSpline ; A plain font was desired
@tryForStyledSpline
tst.l d4 ; See if a styled spline was picked up.
bnz.s @passBackStyledSpline ; ex<71> Un-inline @passBackStyledSpline on way to @setupForLoad
@tryForPlainSpline
tst.l d7 ; See if a plain TrueType font was picked up.
bnz.s @passBackPlainSpline ; Weve got a TrueType version. Go use it.
; A plain spline couldnt be found. Before we go back to try subsituting, go back and
; look for a styled spline if QuickDraw was asking for a plain font, in case the font
; is styled.
move.l d3,d0 ; <63>
swap d0 ; <63>
tst.w d0 ; <63> Check the style that QuickDraw wanted
bnz.s @sizeAndStyleNotFound ; <64> If QuickDraw wanted a style, we didnt find it, so go subsitute
; QuickDraw was asking for a plain font. Before we go look at the a styled alternate, change
; the requested style to be non-plain so we dont infinite loop if there is no styled alternate
; either.
swap d3 ; <64>
move.w #1,d3 ; <64> Pretend were looking for a style so we dont inifinite loop
swap d3 ; <64>
bra.s @tryForStyledSpline ; <64> Go see if a styled spline was picked up along the way
@passBackPlainSpline
move.l d7,a1 ; Point to the plain cache entry
; Weve got a pointer to the cache entry for the best match we could find in A1.
; Set up the resource chain for the load from this 'FOND'.
@setupForLoad
movem.l (sp)+,d2-d7/a4
move.l LastFOND,a0 ; <59>
move.b FONDState,d0 ; <59> Restore the handle state of the previously cached FOND
_HSetState ; <59>
move.l (a1)+,a0 ; Get FOND handle from list
move.l a0,LastFOND ; <27> Keep the two handles synchronized.
_HGetState ; <59> Get the current state of the 'FOND' handle
move.b d0,FONDState ; <59> Save the state of the handle
_HNoPurge ; <59> Dont let it get purged while were using it.
move.l (a1),a1 ; Get handle to resource map that contains this FOND
move.l (a1),a1
move.w 20(a1),d0 ; Remember this resource maps refNum.
move.l ExpandMem,a1
move.l ExpandMemRec.emSplineKey(a1),a1
move.l (a1),a1
move.w d0,splineKeyRec.lastFontMap(a1) ; Save map this font was fetched from
move.w d0,CurMap ; Set up the map to fetch from
move.l a0,d0 ; Move the 'FOND' into D0 to set up condition code
rts
;
; If we got here, we couldnt find a good enough match for the desired size and style.
; Set the condition codes to go back and try scaling another size.
;
@sizeAndStyleNotFound
movem.l (sp)+,d2-d7/a4 ; <24> Restore these buggers.
moveq #0,d0 ; Tell NewFontLookup to try scaling.
rts
;_________________________________________________________________________________________
;
; A new FOND list has been created. Cache it. Always move the second cache entry into
; the first one, and store the new FOND list in the second cache entry. A2 contains the
; handle to cache on entry.
;
CacheFONDList
movem.l a0-a1/d0,-(sp)
move.L expandMem, a1 ; Get low mem expand
move.l ExpandMemRec.emSplineKey(a1),d0 ; Get TrueType globals
beq.s @noSplineRec ; Get out if no globals
move.l d0,a1
move.l (a1),a1
lea splineKeyRec.fondCache(a1),a1 ; Get address of cached FOND list
move.l (a1),d0
beq.s @noHandleInCache
move.l d0,a0
_DisposeHandle ; Get rid of the first list
@noHandleInCache
move.l 4(a1),(a1)+ ; Move second entry up
move.l a2,(a1) ; Store the new list
@noSplineRec
movem.l (sp)+,a0-a1/d0
rts
;_________________________________________________________________________________________
;
; Look for a FOND list from the cache in SplineKey. Returns a handle in A2 if a list is
; found. D7 holds the FOND ID on entry.
;
TryForListFromCache
move.L expandMem, A0 ; Get low mem expand
move.l ExpandMemRec.emSplineKey(A0),d0 ; Get TrueType globals
beq.s @noSplineRecord ; Oops! No cache!
move.l d0,a0
move.l (a0),a0
lea splineKeyRec.fondCache(a0),a0 ; Get address of cached FOND list
moveq #1,d1
@checkCache
move.l (a0)+,d0 ; See if theres a FOND list
beq.s @checkNextCacheEntry ; If not, try the other one
move.l d0,a2
move.l (a2),a2
cmp.w (a2),d7 ; Right FOND?
beq.s @foundListInFOND ; Yep.
moveq #0,d0 ; Clear out D0 in case we fall through.
@checkNextCacheEntry
dbra d1,@checkCache
@foundListInFOND
move.l d0,a2
tst.l d0
@noSplineRecord
rts
;_________________________________________________________________________________________
;
; Search the font chain for all FOND resource with the correct family ID. Build a list of
; sizes and styles referenced by each family record.
;
GetCandidateFONDs
FindFONDFrame Record {A6Link},Decr
sizeList ds.l 1
paramBegin equ *
fontNum ds.w 1
useApplFont ds.w 1
paramSize equ paramBegin - *
retAddr ds.l 1
A6Link ds.l 1
oldCurMap ds.w 1
localSize equ *
EndR
With FindFONDFrame
link a6,#localSize
movem.l a2-a4/d1/d5-d7,-(sp)
move.w fontNum(a6),d7 ; Get FOND ID
cmpi.w #applFont,d7 ; <56> Did applFont get passed in for some reason?
bne.s @notApplicationFont ; <56> No
move.w ApFontID,d7 ; <56> If so, subsitute in real font ID for application font.
@notApplicationFont
move.w CurMap,oldCurMap(a6) ; Everybody remember where we parked!
move.l TopMapHndl,a3 ; <37> Start searching from the top resource map
move.l (a3),a0 ; <37>
move.w mRefNum(a0),CurMap ; <37> <41> Start looking for fonts from the top
bsr.s TryForListFromCache ; Try to get a FOND list from the cache
bne @exitFindFONDS ; If got something from the cache, get out.
;
; First do a quick check to see if the requested font is available. If not, use the
; application font.
;
subq #4,sp
move.l #'FOND',-(sp) ; Look for a font family record
move.w d7,-(sp) ; Font family
move.w #MapTrue,ROMMapInsert ; Look in ROM, too.
_GetResource ; Try to get it.
move.l (sp)+,d0
bne.s @fontFamilyAvailable ; Go on if this font family exists.
tst.w useApplFont(a6) ; Use application font if fontNum doesnt exist?
bne.s @useApplicationFont ; Yep. Assume that application font is always available.
moveq #0,a2 ; Return nothing
bra @exitFindFONDs
@useApplicationFont
move.w ApFontID,d7 ; If not, use the application font.
@fontFamilyAvailable
moveq #4,d0
_NewHandle ,Sys,Clear
move.l a0,a2 ; Handle for size list
bsr CacheFONDList ; Place the handle in the cache.
move.l (a0),a0
move.w d7,(a0)
move.w #-1,2(a0) ; Start at -1, so entry count will be zero based
;
; Find all 'FOND' resources of ID fontNum, and build a list of font sizes these resources contain
;
@findFONDLoop
subq #4,sp
move.l #'FOND',-(sp)
move.w d7,-(sp) ; Low word of D7 has font family number
move.w #MapTrue,ROMMapInsert ; Search the ROM for FONDs too.
_GetResource
move.l (sp)+,d0 ; See if we got anything
beq @exitFindFONDs ; If not, get out.
;
; Figure out which resource map this resource came from.
;
move.l d0,a4
subq #2,sp
move.l a4,-(sp)
_HomeResFile ; See where the resource came from
move.w (sp)+,d0 ; Get the file reference number
cmpi.w #0,d0 ; Special case for System file
bne.s @findMapLoop
moveq #2,d0
@findMapLoop
move.l a3,a0 ; Remember this map.
move.l a3,d5 ; Keep another copy for putting in our little table
move.l (a0),a0
move.l 16(a0),a3 ; Save next map
cmp.w 20(a0),d0 ; Is it the the right map?
beq.s @parseFOND ; <54> Weve found the right map. Now check out the font assocation table entries.
move.l a3,d1 ; <54> See if weve hit the bottom of the chain without finding the map the font came from
bz.s @exitFindFONDs ; <54> If this is the case, just exit.
bra.s @findMapLoop ; <55> Loop back to find the right map.
;
; Parse the FOND for the sizes it contains
;
@parseFOND
move.l (a4),a1
lea FontFamilyRecord.FONDAssoc(a1),a1 ; Get FOND association table
move.w (a1)+,d6 ; Get number of entries
bmi.s @exitFindFONDs ; <61> If the entry count is less than 0, bail
@addEntryLoop
move.l a2,a0
_GetHandleSize
move.l d0,d1 ; Save a copy of the size
add.w #kFONDListSize,d0
_SetHandleSize ; Increase list size by another entry
bne.s @exitFindFONDS ; Bail out if the list couldnt be expanded
move.l (a0),a0
add.w #1,2(a0) ; Increment the count of entries in list
add.l d1,a0 ; Add entry to the end
move.w (a1),d0 ; Size to look for styles of
move.w d0,(a0)+ ; Remember this font size
;
; Given a font size, and a handle to a FOND resource, determine all the styles that
; this FOND describes for this size, and form a bitmap of these styles. The bitmap
; is a merger of all the style codes for this font size in the FOND.
;
; <49> Normally, the font association table in a 'FOND' resource is structured such that
; for a given point size, the entry for the plain font comes before the entries for any
; stylistic variations. The following code saves information about the fonts in the
; font family, keeping a record of the plain font, and a record for all the styles. It
; assumes that the font assocation table followed the normal ordering. Of course, were
; talking about Macintosh developers here, who are a breed apart and theres always ONE
; person that doesnt follow the standard. Add a check so that if one of these screwy
; 'FOND's is encountered, the record for the styles is split across the record for the
; plain entry. What Im saying is that the cache entries used to look like:
; [Info for plain][Info for styles]. For a screwy 'FOND', it will look like:
; [Info for styles][Info for plain][Info for more styles].
;
moveq #0,d1 ; Assume only plain style first
tst.b 3(a1) ; Keep the plain font separate since there are no bits to signify plain
bne.s @getStylesLoop
addq #FAssocSiz,a1 ; Point to next entry
bra.s @putStyleInfoInList
@getStylesLoop
cmp.w (a1),d0 ; Is the the right size?
blt.s @gotAllStyles ; If the size in the association table is larger than what we want, were done
tst.b 3(a1) ; <49> Check in case we have a FOND that doesnt have the plain style first
bz.s @gotAllStyles ; <49> If this entry is plain, save off the styles we have so far, and start a new entry for the plain style
or.b 3(a1),d1 ; Merge in the styles in this entry
@tryNextEntry
addq #FAssocSiz,a1 ; Try next entry
dbra d6,@getStylesLoop ; Or until there are no more entries
@gotAllStyles
addq #1,d6 ; Add one so we can fall through properly at the dbra
@putStyleInfoInList
move.w d1,(a0)+ ; Remember which styles this FOND contains
move.l a4,(a0)+ ; And this FOND resource
move.l d5,(a0)+ ; And which resource map it was in
dbra d6,@addEntryLoop ;
;
; All the sizes have been sucked out of this FOND. Set up the font chain to point
; to the file below the one that this FOND was found in, and try from there. At this
; point, A3 still contains a handle to that next resource map.
;
@gotSizeForLastFont
move.l a3,d0 ; Check to see if were at bottom
beq.s @exitFindFONDs ; If so, get out of here.
move.l a3,a0
move.l (a0),a0
move.w 20(a0),CurMap ; And set the file reference number
bra @findFONDLoop ; Try with this map
@exitFindFONDS
move.w oldCurMap(a6),CurMap
move.l a2,sizeList(a6) ; Return handle to caller
movem.l (sp)+,a2-a4/d1/d5-d7
unlk a6
move.l (sp)+,a0
addq #paramSize,sp ; Pop parameters
jmp (a0) ; Return to caller
EndWith
;————————————————————————————————————————————————————————————————————
; 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.
;
; Upon entry, the desired font size is on the top of the stack, and
; the desired font family ID is in D3.
;————————————————————————————————————————————————————————————————————
NewFontLookUp
move.w (sp)+,d5 ; get desired size
swap d3
clr.w d3
move.b fmInFace(a3),d3 ; and style we want
swap d3 ; Keep style in high word
move.l d0,a2 ; Get family record
move.w CurMap,-(sp) ; <28> Switch the order of A3 and CurMap on
move.l a3,-(sp) ; <28> the stack so A3 can be restored first.
subq #4,sp
move.w d3,-(sp) ; Pass in the family ID
move.w #1,-(sp) ; Use application font if desired font cannot be found.
bsr GetCandidateFONDs ; Search font chain for all FONDs of this ID.
move.l (sp)+,a3 ; List of sizes
; first go for an exact match
move.w D5,D3
bsr GetFONDForSizeAndStyle ; Find the resource handle of the FOND with the right size
bz.s @tryScaling
move.l a0,a2 ; Then call the old FindSize to load it
bsr FindSize
bvs NewFailedRestore ; <36> Couldnt find one. Restore the resource chain and leave.
beq.s @tryScaling ; <36>
bra.s FoundTheSize ; Now deal with styles
; if FScaleDisable is on, don't bother to look for 2X and .5X first
@tryScaling
TST.B FScaleDisable
BNE.S FindClosest
; now try for the one that's twice the size
ADD.W D3,D3
bsr GetFONDForSizeAndStyle ; Find the resource handle of the FOND with the right size
beq.s @tryHalfSize
move.l a0,a2
bsr FindSize ; And load it if the right size was found
bvs NewFailedRestore ; <36> Couldnt find one. Restore the resource chain and leave.
bz.s @tryHalfSize ; <36>
bra.s FoundTheSize
; try for the half-size one
@tryHalfSize
move.w D5,D3
lsr.w #1,D3
bcs.s FindClosest ; skip if the original size is odd.
bsr GetFONDForSizeAndStyle ; Try to find a FOND for this size
bz.s FindClosest ; or try scaling with the closest size
move.l a0,a2
bsr FindSize ; If a FOND was found, load it up
bvs.s NewFailedRestore ; <36> If one couldnt be found, panic
beq.s FindClosest ; <36> or try scaling with the closest size
bra.s FoundTheSize ; now worry about points for style
; oh, well, beggars can't be choosers. Scan to find the closest one
; in size
FindClosest
MOVE.L (A3),A0 ; point to size list
addq #2,a0 ; <25> Skip FOND ID.
MOVE.W (A0)+,D4 ; get # of entries-1
MOVEQ #0,D1 ; no font yet
MOVE #$7FFF,D2 ; closest delta so far
; ex<73>.2 Let sfnt be misinterpreted as 0pt NFNT
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.w D0,D2 ; remember the size difference
move.w (A0),D1 ; remember font size, too
NxtSizeLoop
add.w #kFONDListSize,A0 ; bump to next entry
DBRA D4,Scan4SizeLoop ; search them all
sizeFound
move.w D1,D3 ; get best alternative
BSR GetFONDForSizeAndStyle ; Try to find a FOND for this size
beq.s NewFailedRestore
move.l a0,a2
bsr FindSize ; If a FOND was found, load it up
BVS.S NewFailedRestore ; <36> If we STILL cant find a font, then
beq.s NewFailedRestore ; <36> were REALLY hosed!
;—————————————————————————————————————————————————————————————————————————
; OK, we found the size so now worry about the style. The Font handle is
; saved in D0.
FoundTheSize
move.l (sp)+,a3 ; Restore A3
MOVE.L A0,D0 ; save the font handle in D0
MOVE.L (A2),A0 ; handle->pointer
LEA FontFamilyRecord.FONDAssoc(A0),A0 ; skip header
MOVE.W (A0)+,D1 ; fetch # of entries
MOVE.L WidthTabHandle, A1 ; Get the Width Table Handle
MOVE.L (A1), A1 ; Get pointer to Width Table
TST.B WidthIsSpline(A1) ; Did a spline match
BNE.S GotEntry ; Is spline so branch
FTSLoop
CMP.W (A0),D3 ; search for matching size
BEQ.S GotEntry
ADDQ #FAssocSiz,A0
DBRA D1,FTSLoop
_Debug ; when could this ever fall through?
bra.s NewFailed
NewFailedRestore ; we can't find any in the family FOND record so try the old way
move.l (sp)+,a3 ; Restore A3
NewFailed
move.w (sp)+,CurMap ; <28> Pop CurMap in NewFailed in case were coming from FoundTheSize
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.
; 2.8 CEL Added Spline Font Style selection. Plus needed spline font width table initialization.
;
; 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.
;
;
; Registers on Entry:
; A0 = FOND data pointer
; A2 = FOND handle
; A3 = input record
; D0 = font handle
; D1 = left in assoc. table
; D3 = actual size
;
; Registers used:
; A1 = best style entry
; A4 = offset to width table in FOND
; D2 = user style descriptor, scratch
; D4 = best style weight, temp.
; D6 = FOND style descriptor
;
; CLOBBERS:
; D5 = scratch
; D7 = scratch
;
;————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
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
MOVE.L A0, -(SP) ; save off regs for now
BSR DerefWidthTab ; get pointer to widthtable
TST.B WidthIsSpline(A0) ; is it spline
BEQ.S @notSpline ; not a spline
MOVE.L (SP)+, A0 ; restore A0
TST.W (A0)+ ; Spline always 0
BEQ.S @checkBranch ; test for looping
BRA.S @foundMatch0 ; pass up loop
@notSpline
MOVE.L (SP)+, A0 ; restore A0
CMP.W (A0)+,D3 ; next one same size?
@checkBranch ; <2.7-4april89-CEL>
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 fontHandle
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.)
; << Clobbers 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
move.w (sp)+,CurMap ; <28> Restore the resource map now
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 FontFamilyRecord.FONDLast(A1),D1 ; get lastChar
BEQ.S @noFamWidths ; if zero, must be a “null” FOND set up by Font/DA Mover
SUB.W FontFamilyRecord.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 FontFamilyRecord.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 ; drskip 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 cant see any trivial 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 ---
@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
CMP (A1),D0 ; exact match?
BEQ.S @figureWidthPos ; dont worry no more
NOT D0 ; set all cleared bits
AND (A1),D0 ; nonzero if style in width is not in request
BNE.S @wrongFamWidths ; dont consider widths with too much info.
MOVEQ #0,D5 ; accumulated weight
MOVE (SP),D0 ; bits in requested style
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
MOVE.L D6,A1
@figureWidthPos
MOVE (A1)+,fwidStyle(A6) ; keep best found style
SUB.L (A2),A1
MOVE.L A1,A4
@tossStackSpace
ADDQ #2,SP
@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
if forROM or HAS_COLOR then
FPointOne
else
BWFPointOne
endif
DC.W 1
DC.W 0
; StyleTable for the Screen -- note this is changed from old ROM; no
; more extra for bold and italic.
ScreenStyleTab
DC.W 80,80 ; dots/inch
DC.B 0,1,1 ; bold
DC.B 1,8,0 ; italic
DC.B 0,0,0 ; underline (stub)
DC.B 5,1,1 ; outline
DC.B 5,2,2 ; shadow
DC.B 0,0,$FF ; condensed
DC.B 0,0,1 ; extended
DC.B 1,1,1 ; underline (for real)
Theft
DC.B $00,$77,$7A,$3B,$C9,$35,$30,$19
DC.B $80,$AF,$30,$18,$7A,$60,$18,$09
DC.B $00,$60,$31,$98,$09,$72,$7B,$BA
DC.B $49,$BF,$E0,$9D,$01,$02,$20,$BF
DC.B $40,$88,$01,$F1,$FE,$02,$0A,$81
DC.B $BC,$04,$07,$03,$9A,$08,$04,$0F
DC.B $80,$99,$1F,$C0,$37,$60,$B9,$0F
DC.B $04,$03,$DF,$0F,$98,$08,$37,$60
DC.B $1F,$C1,$A8,$04,$0F,$80,$02,$02
DC.B $9A,$01,$04,$87,$08,$18
EndWith
; PROCEDURE GetFontName(familyID: INTEGER; VAR theName: Str255);
;
; Get the name of the font, given the family ID
if forROM or HAS_COLOR then
GetFontName
else
BWGetFontName
endif
; 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
MOVE.W #MapFALSE,ROMMapInsert ; don't load the font
SUBQ #4,SP ; make space for function result
MOVE.L #'FONT',-(SP) ;'FONT' is resType
MOVE.W D1,-(SP) ; push ID
_GetResource ; get the named resource handle
MOVE.L (SP)+,D0
MOVE.L D0,A0
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.
;
; 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
; MOVE.W #MapTrue,RomMapInsert ; look in ROM first <SM19> rb <Sys7.1> Don't!
_GetResource ; look for it
MOVE.L (SP)+,D0
MOVE.L D0,A0
RTS
; FUNCTION RealFont(famID: INTEGER; size: INTEGER): BOOLEAN;
;
; 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.
if forROM or HAS_COLOR then
RealFont
else
BWRealFont
endif
With SwapFontStackFrame
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 not real
move.l a1,-(sp) ; Save A1 since GetCandidateFONDs doesnt.
subq #4,sp
move.w d1,-(sp)
clr.w -(sp) ; Dont use the application font if font family isnt found
bsr GetCandidateFONDs ; Use candidate list
move.l (sp)+,d0
move.l (sp)+,a1 ; Restore A1
move.l d0,-(sp) ; <60> Save the candidate list
beq.s @oldKindOfFont
; GetCandidateFONDs returns a list of available sizes for this font family. Scan this
; list for the requested size.
move.l d0,a0
_HLock ; <60> Lock the candidate list
MOVE.L (A0),A0 ; handle->pointer
addq #2,a0 ; Skip past family ID
MOVE.W (A0)+,D0 ; pick up the count
BMI @notReal ; if none, skip <14-jlf>
@nrfLoop
tst.w (a0) ; Size 0 means its a spline font.
bz.s @checkPPEM ; <50> Check the lowest size TrueType is used for.
cmp.w (a0),d2 ; got it?
beq @itsReal ; if so, its real
@nextCandidate
add.w #kFONDListSize,A0 ; skip to next entry
DBRA D0,@nrfLoop ; check em all out
BRA.S @notReal ; it must not be real...
; <50> Weve got an entry for a TrueType font. Instead of automatically
; returning true, call fs_LowestPPEM to see if the TrueType font will be
; used to draw this point size. If it is, go ahead and return true. If
; it wont, go back into the loop and look for a bitmapped size.
@checkPPEM
movem.l d0/a0-a2,-(sp) ; <50>
move.w CurMap,-(sp) ; <52> Save the current resource map.
move.l FONDMap(a0),a2 ; <52> Get the resource map handle
move.l (a2),a2 ; <52>
move.w mRefNum(a2),CurMap ; <52> Make this map the current resource map
move.l FONDHandle(a0),a2 ; <50> Get handle to FOND containing spline entry
tst.l (a2) ; <50>
bnz.s @fondIsLoaded ; <50>
move.l a2,-(sp) ; <50>
_LoadResource ; <50> Make sure its loaded
@fondIsLoaded
move.l (a2),a2 ; <50>
lea FontFamilyRecord.FONDAssoc+2(a2),a2 ; <50> Point to font association table (after entry count)
; The TrueType entry in the font association table should always be first, but
; do a loop just in case. This loop assumes that the entry in the candidate entry
; is correct, and that a spline font will eventually be found in this font association
; table.
@findSplineEntry
tst.w (a2) ; <50> Is this the spline entry?
bz.s @gotSplineEntry ; <50> If the size is 0, then it is
addq #fAssocSiz,a2 ; <50> Otherwise, point to the next entry
bra.s @findSplineEntry ; <50>
; Found the entry in the font association table for the TrueType version of this font.
; Load the spline resource, then call LowestPPEM to find out the lowest point size that
; TrueType will be used for. If the requested size is larger than this size, then
; return true. If the requested size is smaller than this size, then continue searching
; the candidate list for a bit map.
@gotSplineEntry
move.w 4(a2),d0 ; <50> Pass the ID of the 'sfnt' resource
bsr LoadSplineFontResource ; <50> Go get it.
move.w d2,-(sp) ; <53> Save the size were looking for.
subq #2,sp ; <50>
move.l d0,-(sp) ; <50> Pass TrueType font handle to fsLowestPPEM
_fsLowestPPEM ; <50> Find out the lowest size TrueType will be used for
move.w (sp)+,d0 ; <53> Get the lowest size TrueType should be used for
move.w (sp)+,d2 ; <53> Restore the requested size.
cmp.w d0,d2 ; <50> Compare against the requested size
blt.s @tryForBitMap ; <50> If the requested size is less, look for an actual bitmap size
move.w (sp)+,CurMap ; <52> Restore the current resource map.
movem.l (sp)+,d0/a0-a2 ; <50>
bra.s @itsReal ; <50> If TrueType will be used for this size, this should be considered an available size.
@tryForBitMap
move.w (sp)+,CurMap ; <52> Restore the current resource map.
movem.l (sp)+,d0/a0-a2 ; <50>
bra.s @nextCandidate
@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
link a6,#stackFrame ; <38> GetStrike uses the FMSwapFont stack frame now
move.w d1,styleID+2(a6) ; <38> Save the resource ID here
BSR GetStrike ; do we have it
unlk a6 ; <38> Done with the stack frame
BEQ.S @notReal ; good! (branch if we couldn't find it)
@itsReal
ADDQ.B #1,4(SP) ; return TRUE <60> The candidate handle is still on the stack
@notReal
move.l (sp)+,a0 ; <60> Get the candidate handle
_HUnlock ; <60> Let it float
JMP (A1) ; return to caller
;
; Utility called by GetFNum
TryForName
SUBQ #4,SP ; make room for function result
; MOVE.L D1,-(SP) ; push the resource class
; MOVE.L 12(SP),-(SP) ; push the name pointer
MOVE.L D0,-(SP) ; push the resource class
MOVE.L D1,-(SP) ; push the name pointer
MOVE.W #MapFALSE,ROMMapInsert ; do with ResLoad false <10 Jul 85>
_GetNamedResource ; get the resource
MOVE.L (SP)+,D0 ; did it get it?
RTS
EndWith
; PROCEDURE GetFNum(familyName: Str255; VAR theID: INTEGER);
;
; Get the family ID of the font, given the name
;
; Modification History:
;
; 26-Aug-86 CRC Take advantage of new Resource Manager + code crunching
; 29-Aug-86 CRC A preliminary version of MacAuthor depends on D2 being preserved.
if forROM or HAS_COLOR then
GetFNum
else
BWGetFNum
endif
MOVE.L 8(SP),D1 ; move string address to register
MOVE.L (SP)+,4(SP) ; place return address at top of frame
MOVE.L (SP)+,A1 ; get pointer to ID.
MOVE.L #'FOND',D0 ; resource type
BSR.S TryForName
BNE.S @gotFondFID
MOVE.L #'FONT',D0 ; resource type
BSR.S TryForName
BNE.S @gotFontFID
CLR.W (A1) ; make it NIL
BRA.S @doneGFID ; all done
; we got it, so look up the ID
@gotFondFID
ST D1
BRA.S @gotFID
@gotFontFID
SF D1
@gotFID
MOVE.L D0,-(SP) ; push the resource handle
MOVE.L A1,-(SP) ; place for ID
CLR.L -(SP) ; no type
CLR.L -(SP) ; no name
MOVE.W #MapFALSE,ROMMapInsert ; get from ROM if possible <10 Jul 85>
_GetResInfo ; get it!
; CMP.L #'FOND',D1 ; new way? (old way!)
TST.B D1 ; got FOND?
BNE.S @doneGFID ; if so, already done
MOVE.W (A1),D0 ; get the ID
LSR #7,D0 ; divide by 128
MOVE.W D0,(A1) ; return the ID
; all done so restore registers and return to caller
@doneGFID
; MOVE.L D2,(SP) ; overwrite location of string with return address
RTS
; PROCEDURE SetFontLock(lockFlag:Boolean) -- makes the current font purgable
; or unpurgable.
if forROM or HAS_COLOR then
SetFontLock
else
BWSetFontLock
endif
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 FOutFontHandle,a0 ; get the current font handle <14-jlf>
tst.l (a0) ; is it purged? <14-jlf>
bne @NoPurgeFont ; no, skip the resource load stuff <14-jlf> <Sys7.1> Unshortened branch
move.l WidthTabHandle,a0 ; get current width table <14-jlf>
move.l (a0),a0 ; get master pointer <14-jlf>
tst.b WidthIsSpline(a0) ; is this a spline font? <14-jlf>
beq @DoNormalFontLock ; no, do normal stuff <14-jlf> <Sys7.1> Unshortened branch
tst.b KeepSplineOnDisk(a0) ; should the spline be loaded into memory? <14-jlf>
bne @doneSFL ; no, bail out of routine <14-jlf> <Sys7.1> Unshortened branch
move.w WidthStrikeID(a0),d0 ; setup sfnt resource id parameter <14-jlf>
jsr LoadSplineFontResource ; call the load routine <14-jlf>
bsr DerefWidthTab ; get widthPointer in a0 <14-jlf>
exg d0,a0 ; exchange splineHandle with widthTable <14-jlf>
tst.l (a0) ; was the spline loaded into memory? <14-jlf>
exg d0,a0 ; swap the registers back <14-jlf>
seq KeepSplineOnDisk(a0) ; don't try to load next time if not loaded <14-jlf>
beq @doneSFL ; skip the nopurge if it wasn't loaded <14-jlf> <Sys7.1> Unshortened branch
bra @NoPurgeFont ; make it non-purgeable <14-jlf> <Sys7.1> Unshortened branch
@DoNormalFontLock
MOVE.L FOutFontHandle,A0 ; get the font handle <14-jlf>
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
@NoPurgeFont ; <14-jlf>
_HNoPurge ; turn off purge bit
BCLR #purge,FondState
BRA.S @doneSFL
; we no longer need the font so make it purgable
@unlockFont
MOVE.L FOutFontHandle,A0 ; get the font handle
_HPurge ; make it purgable
BSET #purge,FondState
@doneSFL
JMP (A1) ; return to caller
IF forROM OR NOT HAS_COLOR THEN
; PROCEDURE SetFScaleDisable(scaleDis:BOOLEAN);
;
; Set to turn ScaleDisable on and off, invalidating the width cache.
if forROM or HAS_COLOR then
SetFScaleDisable
else
BWSetFScaleDisable
endif
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.
if forROM or HAS_COLOR then
SetFractEnable
else
BWSetFractEnable
endif
MOVE.L (SP)+,A0 ; return address
MOVE.B (SP)+,FractEnable
BRA.S setFScaleTail
ENDIF
; PROCEDURE FontMetrics(VAR theMetrics:FontMetricRec);
;
; 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
if forROM or HAS_COLOR then
FontMetrics
else
BWFontMetrics
endif
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
BSR DerefWidthTab ; Get pointer to width table
TST.B WidthIsSpline(A0) ; Get is spline flag
BEQ.S @notSpline ; not a spline
MOVE.L expandMem, A0 ; get low mem expand
MOVE.L ExpandMemRec.emSplineKey(A0), A0 ; Handle to splineKey
MOVE.L (A0), A0 ; pointer to splinekey
MOVE.L splineKeyRec.cacheHand(A0), D0 ; is there a cache
BEQ.S @bailForZeros
MOVE.L D0, A0 ; get Handle in addr reg
TST.L (A0) ; Is it purged
BEQ.S @bailForZeros ; bail since we have no cache
MOVE.L (A0), A0 ; pointer to the cache
WITH cache ; <8>
MOVE.L ascent(A0), (A2)+ ; Get Ascent out of cache
MOVE.L descent(A0), (A2)+ ; Get Descent out of cache
MOVE.L leading(A0), (A2)+ ; Get Leading out of cache
MOVE.L widMax(A0), (A2)+ ; Get Widmax out of cache
ENDWITH
BRA.S @finishSplines ; Fill in the rest of the Width Table
@bailForZeros
CLR.L (A2)+ ; Zero Ascent
CLR.L (A2)+ ; Zero Descent
CLR.L (A2)+ ; Zero Leading
CLR.L (A2)+ ; Zero Widmax
BRA.S @finishSplines ; Fill in the rest of the Width Table
@notSpline
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
@finishSplines
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
if forROM or HAS_COLOR then
MOVE.L FPointOne,D1
else
move.l BWFPointOne,d1 ; <12> DTY
endif
@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.
;
; 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 QuickDraws table.
LeftMask EQU $20 ; position of left masks in QuickDraws table.
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
hBitDepth EQU -4
locStack EQU hBitDepth
ENDIF
BuildCharTable
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
LINK A6,#locStack
ENDIF ; END colorgrayness
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
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
MOVE (A1),D0 ; get font flags
ASR #2,D0 ; strip height, width bits
AND #$7,D0 ; get bit depth of font <BAL 08May88> @@@@ used to be 3
MOVE D0,hBitDepth(A6)
ENDIF ; END Color Gray Ness
MOVE.W fNDescent(A1),D0 ; possibly the high word of owTLoc
SWAP D0 ; put it in the high word
BPL.S @notNegative
MOVEQ #0,D0
@notNegative
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
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
UNLK A6
ENDIF ; End color grayness
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
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
BEQ EmptyChar
MOVE hBitDepth(A6),D0
LSL D0,D7 ; scale up pixel start
LSL D0,D6 ; scale up remaining width
ELSE
BEQ.S EmptyChar ; if zero, its easy
ENDIF ; End Color Gray Ness
; 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
IF (HAS_COLOR) THEN ; <2.7-4april89-CEL>
MOVE fRowWords(A0),D4
MOVE hBitDepth(A6),D2
LSL D2,D4 ; scale up
ADD D4,D4 ; compute rowBytes
MOVE D4,A0 ; leave in A0
BRA.S @doneBitDepth
MOVE.W fRowWords(A0),A0 ; get rowWords in A0
ADD.W A0,A0 ; compute rowBytes
@doneBitDepth
ELSE
MOVE.W fRowWords(A0),A0 ; get rowWords in A0
ADD.W A0,A0 ; compute rowBytes
ENDIF
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
IF (NOT forROM) THEN
;———————————————————————————————————————————————————————————————————
; getIs32Bit - load the is32Bit flag from the splineKey globals.
;———————————————————————————————————————————————————————————————————
getIs32Bit
MOVE.L A0,-(SP) ; save a register.
MOVE.L expandMem,A0 ; get low memory expand pointer.
MOVE.L ExpandMemRec.emSplineKey(A0),A0 ; get handle to splineKey globals.
MOVE.L (A0), A0 ; get pointer to splineKey globals.
TST.B splineKeyRec.is32bit(A0) ; get 32 bit CQD flag in CCR.
MOVE.L (SP)+,A0 ; restore a register.
RTS ; return to the caller.
ENDIF
if forROM or HAS_COLOR then
FMgrEnd
else
BWFMgrEnd
endif
; END ; <3.3>
;*******************************************************************
;*******************************************************************
;*******************************************************************