supermario/base/SuperMarioProj.1994-02-09/Toolbox/FontMgr/Bass_Cache.c
2019-06-29 23:17:50 +08:00

3093 lines
108 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

/*
File: Bass_Cache.c
Contains: Interfaces between Font Scaler code, QuickDraw and the Font Manager. Retrieves
and caches glyphs. Initializes spline state variables.
Written by: Charlton E. Lui
Date: May 8, 1988
Revision: 1.0
Copyright: © 1988-1992 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<23> 6/22/92 JH #1033107 <AMW>: Changed call to GetEncodingTable to
Font2RealScript.
<22> 5/3/92 JH #1028023 <AMW>: Changing straight jump to fs_NewSfnt to the trap
version. This enables our Korean subsidiary and potentially
other non U.S distributors to patch the NewSfnt trap and look
for a dongle.
<21> 1/3/92 JSM Roll-in changes from Sakura: sb_CheckCache() can return NO_BITS
from sb_RenderGlyph() (seems to only happen when printing with
the StyleWriter), check for this and call
CheckForMaximumDiskCacheSize() in sb_RetrieveGlyph() anyway. We
need to understand this better. Call
DumpFontCacheToDiskIfNotTooBig(), not DumpFontCacheToDisk(), in
sb_DisposeCacheHandle(). Pass squashed to
LoadFontCacheFromDisk(). If banding in TrueType, don't
AddGlyphOffset table more than once in sb_RetrieveGlyph.
<20> 12/9/91 JH #1017215,Fixing problem in sb_SetFontMemory... where if
fs_NewSfnt fails it just bails (calls sb_Debug). The thing about
this is that we (whose we) have released about 16 international
fonts that actually have a specificID of Roman for their CMAP
despite being fonts for scripts other than Roman. These fonts
work on 7.0, but since we now do the right thing in
sb_SetFontMemory (figure out which script the font should belong
to and then use that script for specificID) they won't work for
7.1 (cubee) so to fix that we try again with the Roman platform
ID if the first call to sb_SetFontMemory fails.
<19> 10/23/91 DTY Flush the FOND candidate cache in sb_KillSomeCaches when
everything else is being flushed.
<18> 10/22/91 RB Add support for sfnt-embedded-bitmaps
<17> 9/25/91 jlf Rolled in modifications from Pacific TrueType project and rolled out
DOUBLE_BYTE conditional code.
Added support for double-byte bass caches. The glyphArray field of a
cache is not compatible with double-byte operating systems. Use the
routines in DoubleByteBassCache.c for international support. Added
support for disk caching code through the LoadFontCacheFromDisk and
CheckForMaximumDiskCacheSize routines. The spline directory of a
TrueType font is now appended to it's global width table for partial
font support. sb_SetMemPtrs now accepts a widthTable handle instead of
an sfnt handle in order to initialize the spline sfntDirectory field
of the Scaler input parameter block. Call GetResInfo to obtain the sfntID
in FillPrinterWidths instead of hacking it to zero - it would be nice if
the printer driver passed the sfntID value in, but, that means we would
have to rev all printer drivers that use this call. Added partial font
support. Added disposecachehandle routine to support disk caching (routine
calls DumpFontCacheToDisk before calling disposezonehandle). Call
sb_DisposeCacheHandle in sb_KillSomeCaches instead of letting the cache
handles die through a heap reformat. Replaced calls to sb_DisposeZoneHandle
with cache handle arguments with calls to sb_DisposeCacheHandle. Call
KillApplicationHeapFragmentTableCaches in flush fonts to flush partial
font fragments. Removed static qualifier in front of sb_ShrinkCacheToMin.
Initialize familyID field of a cache in sb_InitCacheHead to the new spline
key global fLastSwapFontFamilyID since the font manager has the obnoxious
habit of setting the fID field of a width table and certain low memory
globals to -1 when the width table is invalidated. This caused major
problems with cmap lookup when using Asian fonts. Added widthTable parameter
to SetFontMemory since it calls SetMemPtrs. Initialized specificID field
of newsfnt input parameter block to the proper script number instead of
hard-coding it to Roman. Always maintain the cache list in the system heap.
sb_NewZoneHandle no longer assumes that the current heap is always the
application heap (this previously caused major heap trashes when the
system font was an outline font). Rolled back in code for MultiFinder
memory allocation (this code relies on a bug fix in 6.x MultiFinder
where the current zone is set to the MultiFinder heap before calling
TempDisposHandle on a purged handle. 7.x systems shouldn't be affected).
Rolled in fixes for bugs found during the development of the background
Tabasco driver (Charlton Lui via Allen Cronce). I friggin' hate this file.
<16> 3/5/91 CL (RB)#82681. Needed to make one more change to sb_searchforcache.
The cache needed to be set to nil to when a cache was
purged.
<15> 2/28/91 CL (KON)(RB)#82681. Making current cache purgeable.
<14> 2/11/91 RB MR, CL,CC,: Fix dropouts when squashing by trying twice to
squash rather than once.
<11> 1/22/91 CL (RB) #81198, #81199. Fixing large glyph crash (ptsize 22,000
pt). Need to pass on error codes.
<10> 12/11/90 MR Improve squishing math, use leading from cache for fmLeading.
Low mem hack. [rb]
<9> 11/27/90 MR Change ByteMax() to return an unsigned char, stop caching
algo-styles [rb]
<8> 11/21/90 CL (RB)Adding in scan converter runInMinMode operations. Broke
sb_renderglyph into smaller subroutines.
<7> 10/29/90 CL (RB)if fs_OpenFonts fails we need to get rid of the workhandle
since it is only partially set up for use. Needed to call
sb_setmemptrs before settting the clientid.
<6> 10/23/90 CL (MR)Making the preflight call work better.
<5> 10/23/90 CL Somehow this file got corrupt by either BBS, projector or the
compare file tool??? Fixed it back up!!!
<4> 10/22/90 CL (BKR)Adding runInMinMode code. This will run in a minimal memory
space when memory is very low. Added in banding of character for
low memory situations.
<3> 10/20/90 MR Change transform[2][2] from a fix_one to frac_one
<2+> 10/20/90 MR,rb Change transform[2][2] from a fix_one to frac_one
<2> 10/11/90 CL Set ENTRY_ERROR to skip glyphs with zero scan lines.
<34> 10/9/90 CL Added preflight routine to see if there seems to be enough
room to render the glyphs.
<33> 10/2/90 CL Fixing up memory error handling.
<32> 9/24/90 CL Fixing error handling in sb_renderglyph. Needed to check
the result after sb_renderglyphinfo call.
<31> 9/10/90 CL Added in a shrinkTest to sb_SizeTheBlock to see whether a block
should be resized down. This is good for sizing down the extra
scan converter space needed for large chars and for large bitmapHands.
<30> 9/10/90 CL Now checking if system and app heap is full. If so purge will
be left on. When both heaps are full it will switch back
and forth to try to get the memory. Conditional is in for
Multi-Finder or system memory.
<29> 9/5/90 CL Getting rid of call to sb_Debug in sb_newZoneHandle since it
really is not an error but just a possible temporary failure.
Bug in sb_FlushFonts… needed to zero out the cacheListHand.
<28> 9/4/90 CL Fixing up memory allocations… Bug in sb_GrowZoneHandle - Assigned
new zone before DiposeZoneHandle giving this function possibly
the wrong zone. Reworked sb_GrowZoneHandle, sb_NewZoneHandle
logic. Added in sb_SetCachesNoPurge, sb_SetCachesPurge so caches
would not unneccessarily get purged. Took out splineKeyPtr param
out of sb_DisposeWorkHandle to make code consistent. Took out
extra call to sb_PrepareWorkHandle from sb_CheckCache. Bug in
original sb_GrowZoneHandle code now in sb_SizeTheBlock fix. When
a disposeZoneHandle was called the current cache was not cleared
so it would be used and blamo the heap free list would get
corrupt. Bug in sb_SearchForCache… Must make the font non-purgeable
before calling sb_PrepareWorkHandle and sb_SetNewSFNT. Font got
purged when it should not have. Got rid of the now unneeded
call to sb_initmemory. Major bug in the sb_GrowZoneHandle that
is now in the sb_SizeTheBlock routine. This routine would
dispose a handle without being able to update the variables
from the calling routine. Therefore you could dispose the
handle, try to get a new handle and fail, then try to use the
disposed handle which would of course corrupt the free list
eventually causing major havoc in the system. Bug when calling
sb_shrinkbitmap on a cached contour. Since the scan lines
could be less than the full height the shrink bitmap call would
go to far since it used the full scan height that is cached
in the font cache. Bug when allocating with the new memory
routines the bitmapHand needs to be disposed and cleared if
it is in the quiting apps heap space. Terrible bug in living
in the MultiFinder temp memory and being purgeable. There is
no way to know the zone and we would die if we dipose the handle
not knowing the true zone if it is in the Multi_Finder heap. Fixed
by living only in the system heap and application heap as we did before
just like the init code does now.
<27> 9/4/90 KSM Fix Begin/EndSystem mode bug in sb_NewZoneHandle.
<26> 8/28/90 MR Change SetHandleSize calls to set the correct zone by using
common routines (NewZoneHandle, GrowZoneHandle,
DisposeZoneHandle). Changed WorkHandMem to ResizeWorkHandle.
Added calls to PrepareWorkHandle to pascal routines that use
fsWorkHand but didn't first check it. Moved bitmapHand and
fsWorkHand to use same memory routines as caches.
<25> 8/27/90 MR Fix uninitialized zone in SearchForCache, added call to gestalt
to NOT use system heap if it is not growable.
<24> 8/22/90 MR Change calls to FillWidthTable to pass sfnt handle and rsrc ID
<23> 8/21/90 MR More consistant checking of fsWorkHand for purginess. Still not
completely confident Ive caught every case.
<22> 8/20/90 MR Restructure memory allocation across heaps. New routines:
NewCacheHandle, NewWorkHandle, sb_DisposeZoneHandle. Conditional
code for system_7 and init.
<21> 8/11/90 MR Use splineKey as global instead of passing it as a parameter
<20> 8/10/90 MR Removed conditional MIKE code
<19> 8/10/90 MR Remove disk_cache code, Removed call to ReallocHandle in
SearchForCache (cross-zone bug)
<18> 8/1/90 gbm rid file of vile warnings
<17> 7/20/90 MR change NewHandleSys to NewHandleSys
<16> 7/20/90 MR Remove warnings, cache optimizations, found cacheHand-purge bug
<15> 7/18/90 MR Add Fonts.h to include file list (to define FMOutput since it
was removed from bass_cache.h
<14> 7/16/90 CL Made Finder compatible for the Goudy init.
<13> 7/14/90 MR changed reference from SQRT2 to FIXEDSQRT2
<12> 7/13/90 MR Changed to use union in FSInput
<11> 7/2/90 RB No change, just get comments synched
<9+> 7/2/90 RB bbs screwup
<9> 7/2/90 CL Fixed runtime conditional to make sure it clips when needed.
<8> 7/2/90 CL Reworked sb_renderGlyph… Now clips the character if squishing
was not enough. Took out encryption.
<7> 5/29/90 CL Took out cache references from the widthtables. Fixed printer
Font Scaler reset bug.
<6> 5/3/90 CL Adding shutdown proc for bass clean up. More work on disk
caching. Removed extra part of transform matrix not needed by
system. In sb_FlushFonts got rid disposed of Handles that had
nil pointers. Adding support for new encryption scheme and scan
converter. Added new memory area
<5> 4/10/90 CL Added support for double byte codes. Worked on disk caching.
Fixed squishing routine.
<4> 3/24/90 CL Font Scaler is returning totally bogus values causing terrible
stack corruption. Added range checking so we can handle these
values.
<3> 3/20/90 CL Adding Disk Cache… Support for the tag format
<2> 2/27/90 CL Added lots of support for DrTexts optimizations. Added a
routine to shrink bitmaps after the Font Scaler call and save a
possible 2x in memory usage. Re-wrote renderglyph.
<2.0> 11/16/89 CEL Fix in sb_fillprinterwidths. Bad assign from ReallocHandle.
<1.9> 11/15/89 CEL Oops forgot to check memerr in sb_fillprinterwidths.
<1.8> 11/14/89 CEL Added device metrics. Added device capabilities.
<1.7> 9/28/89 CEL KillSomeCaches now make sure to get rid of purged font handles
also.
<1.6> 9/25/89 CEL Was setting numer and denom back to identity for splines since
splines do the stretch but this would cause bad font manager
matching. Let the v and h factors to be set back to 1. Added
back in rounding of widths for width table when fractenable is
off.
<1.5> 9/15/89 CEL Checking in just in case something changed that reflects the
Bass_Cache.h file.
<1.4> 8/28/89 CEL Put in conditional for debugger state. Only drops into debugger
if flag is set by hacker.
<1.3> 8/14/89 CEL Added in new encryption checks. Looks in more places for bitmap
temp memory.
<1.2> 8/1/89 CEL Fixed EASEs “C” comment brackets. On check in they were wrong!
<1.1> 8/1/89 CEL Fixed the include file buffer.h to be Bass_Cache.h
<1.0> 8/1/89 CEL Adding into Bass build for the first time…
<1.9> 8/1/89 CEL Fixed over-run array bug. Re-worked data structures.
<1.8> 6/13/89 CEL Integrated Sampos changes to the GlyphInputType…
<1.7> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
file (colorequ.a), got rid of QuickDraw nFiles dependencies and
fixed up necessary files…
<1.6> 6/2/89 CEL Took out hard coded ascent, descent, leading calculations…
<1.5> 5/26/89 CEL Integrated the new Font Scaler 1.0 into Spline Fonts
<1.4> 5/15/89 CEL Bug in sb_SearchForCache - compared purged cache
<1.3> 5/3/89 CEL Comment brackets were previously messed up from override
<•1.2> 5/3/89 CEL All kinks worked out, Blasting in bass files…
<•1.1> 5/2/89 CEL Changed glue.h include file to BassGlue.h
<1.0> 5/1/89 cel Adding Bass for first time…
To Do:
*/
/*********************/
/** System Includes **/
/*********************/
#include "BaseIncludes.h"
#include <types.h>
#include <Errors.h>
#include <memory.h>
#include <MFPrivate.h>
#include <QuickDraw.h>
#include <FixMath.h>
#include "ToolUtils.h"
#include <resources.h>
#include <Script.h>
#include <ShutDown.h>
#include <Fonts.h>
#include <GestaltEqu.h>
#include <SysEqu.h>
#include <ScriptPriv.h>
/*********************/
/** BASSs Includes **/
/*********************/
#include "FSCdefs.h"
#include "FontScaler.h"
#include "MacExtra.h"
#include "FragmentTable.proto"
#include "PartialFontExtensions.proto"
#include "Bass_Cache.h"
#include "SplineError.h"
#include "FontMath.h"
#include "sfnt.h"
#include "DoubleByteBassCache.h"
#include "DiskCacheExtensions.proto"
/* prototypes for DoubleByteBassCache.c routines */
OSErr AddLowByteGlyphOffsetTable( uint16 glyphID, sb_SplineKeyHdl splineKey );
uint32 GetSingleOrDoubleByteGlyphEntryOffset( uint16 glyphID, sb_CacheHeadPtr cachePointer );
extern pascal EncodingTablePointer GetEncodingTable( short fondID, uint16 *scriptCodePointer );
//
//The trap version of this trap is deffed out unless MACINIT is true
//so just define a new constant here, FS_NEWSFNT is defined in FontScaler.h <22>
//
pascal int32 __NewSfntTrap(fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
= {0x303C,FS_NEWSFNT,0xA854};
#ifndef INITVERSION
#define SYSTEM_7
#endif
#ifdef DEBUG
N2S(unsigned long n, Str255 s)
{
short i;
for (i = 10; i > 0; i--)
{
char c = n % 10;
s[i] = '0' + c;
n /= 10;
}
s[0] = 10;
}
HeapCheck()
{
Str255 s;
s[0] = 0;
s[++s[0]] = ';';
s[++s[0]] = 'h';
s[++s[0]] = 'c';
s[++s[0]] = ';';
s[++s[0]] = 'g';
s[++s[0]] = ';';
DebugStr(s);
}
#endif
extern Boolean MultiFinderExist();
extern long PurgeSpaceSysTotal();
long sb_SetUpWorkHand();
/***********************************************************************************************/
/***********************************************************************************************/
/***********/
/** DEBUG **/
/***********/
static void sb_Debug()
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
if ((*splineKey)->callDebug) Debugger();
} /* End sb_Debug */
static char *sb_ReturnDataPointer ( sfntHand, offset, length )
Handle sfntHand;
long offset, length;
{
int i = length;
return( *sfntHand + offset );
}
static long LONG_WORD_ALIGN ( long n )
{
return( (n + 3) & ~3 );
}
static unsigned char ByteMax ( Fixed n )
{
register short shortVal = FixRound(n); /* get rid of low bits */
if (shortVal > 255) shortVal = 255;
return(shortVal );
}
static char ByteRange ( Fixed n )
{
register short shortVal = FixRound(n); /* get rid of low bits */
if (shortVal > 127) shortVal = 127;
else if (shortVal < -127) shortVal = -127;
return(shortVal);
}
/***********************************************************************************************/
/******************/
/** MEMORY CALLS **/
/******************/
/*********************************************************************************************
** sb_DisposeZoneHandle
**
** Allocations are made in different zones and a handle may be purged. When this is the case
** the memory manager does not have the ptr to figure out what zone it is coming from so it
** can not hook the memory links up correctly.
**
** Switch to the correct zone and dipose the handle and then return back to the previous zone.
**
** <28-CEL> added some comments
**
*/
void sb_DisposeZoneHandle(Handle h, THz zonePtr)
{
THz prevZone = GetZone();
OSErr error = noErr;
if (zonePtr) {
SetZone(zonePtr);
DisposHandle(h);
SetZone(prevZone);
} else MFTempDisposHandle(h, &error);
} /* End sb_DisposeZoneHandle */
/*********************************************************************************************
** sb_SetCachesNoPurge <28-CEL>
**
** Run through the caches which have not been purged and make them non-purgeable
**
** WHEN TO CALL: System heap allocation
** WHY: System heap only guestimates when to grow which can cause purgeability or caches.
**
*/
void sb_SetCachesNoPurge()
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
if (splineKeyPtr->cacheListHandle) {
register short fontCount = splineKeyPtr->fontCount;
register CacheReference* cacheRef = *splineKeyPtr->cacheListHandle;
for (--fontCount; fontCount >= 0; --fontCount) {
if (cacheRef->cache && *cacheRef->cache) /* have a ptr??? */
HNoPurge(cacheRef->cache);
cacheRef++;
}
}
} /* End sb_SetCachesNoPurge */
/*********************************************************************************************
** sb_SetCachesPurge <28-CEL>
**
** Run through the caches which have not been purged and make them purgeable
**
** WHEN TO CALL: After system heap memory allocations have been made,
** if sb_SetCachesNoPurge was called.
**
*/
void sb_SetCachesPurge()
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register Handle curCacheHand = splineKeyPtr->cacheHand;
if (splineKeyPtr->cacheListHandle) {
register short fontCount = splineKeyPtr->fontCount;
register CacheReference* cacheRef = *splineKeyPtr->cacheListHandle;
for (--fontCount; fontCount >= 0; --fontCount) {
if (cacheRef->cache && *cacheRef->cache) /* have a ptr??? */
HPurge(cacheRef->cache);
cacheRef++;
}
}
if (curCacheHand && *curCacheHand) HNoPurge(curCacheHand); /* Keep current cache non-purgeable */
} /* End sb_SetCachesPurge */
#ifndef USE_SYSTEM_HEAP
/*********************************************************************************************
** sb_MultiFinderHandle <30-CEL>
**
** Call the Mutlifinder memory manager.
** Since this is system type memory make sure to turn on BeginSystem mode to make
** sure Multifinder does not release the memory when the application quits!
**
*/
Handle sb_MultiFinderHandle(long blockSize)
{
register Handle h;
OSErr resultCode;
BeginSystemMode();
h = MFTempNewHandle((Size)blockSize, &resultCode);
EndSystemMode();
if (resultCode) return nil;
else return h;
} /* End sb_MultiFinderHandle */
#endif
/*********************************************************************************************
** sb_GetSysHandle <30-CEL>
**
**
*/
Handle sb_GetSysHandle(long size)
{
register Handle h = nil;
#ifdef USE_SYSTEM_HEAP
h = NewHandleSys(size); /* system heap mem */
#else
h = MultiFinderExist( ) ? sb_MultiFinderHandle( size ) : NewHandleSys( size );
#endif
return h;
} /* End sb_GetSysHandle */
/*********************************************************************************************
** sb_GetSysHandleZone <30-CEL>
**
**
*/
Handle sb_GetSysHandleZone(long size, THz* zone)
{
register Handle h = nil;
#ifdef USE_SYSTEM_HEAP
h = NewHandleSys(size); /* system heap mem */
*zone = SystemZone(); /* <30-CEL> */
#else
if ( MultiFinderExist( ) ) {
h = sb_MultiFinderHandle( size );
*zone = 0;
} else {
h = NewHandleSys(size);
*zone = SystemZone( );
}
#endif
return h;
} /* End sb_GetSysHandleZone */
/*********************************************************************************************
** sb_GetAppHandleZone <30-CEL>
**
**
*/
Handle sb_GetAppHandleZone(long size, THz* zone)
{
register Handle h;
register THz curZone = GetZone();
register GrowZoneProcPtr growZonePtr = curZone->gzProc;
curZone->gzProc = nil;
h = NewHandle(size); /* <30-CEL> Try the App Heap */
curZone->gzProc = growZonePtr; /* restore the grow zone proc ptr */
*zone = curZone;
return h;
} /* End sb_GetAppHandleZone */
/*********************************************************************************************
** sb_GetAppHandle <30-CEL>
**
**
*/
Handle sb_GetAppHandle(long size)
{
register Handle h;
register THz curZone = GetZone();
register GrowZoneProcPtr growZonePtr = curZone->gzProc;
curZone->gzProc = nil;
h = NewHandle(size); /* <30-CEL> Try the App Heap */
curZone->gzProc = growZonePtr; /* restore the grow zone proc ptr */
return h;
} /* End sb_GetAppHandle */
/*********************************************************************************************
** sb_GrowAppHandle <30-CEL>
**
**
*/
long sb_GrowAppHandle(Handle h, long size)
{
THz curZone = GetZone();
GrowZoneProcPtr growZonePtr = curZone->gzProc;
curZone->gzProc = nil;
SetHandleSize(h, size); /* <30-CEL> took out set and restore zone for sethandlesize */
curZone->gzProc = growZonePtr; /* restore the grow zone proc ptr */
return MemError(); /* <30-CEL> */
} /* End sb_GrowAppHandle */
/*********************************************************************************************
** sb_NewZoneHandle
**
** BEHAVIOR: <28-CEL> some logic
** 7.0 -
** • Make caches non-purgeable
** • Try for Multi-Finder temp memory.
** • Failure: Try for Application memory.
** • Failure: Make caches purgeable and try again from the top.
** (Better)Selectively choose caches for purgeability.
** 6.0 -
** Multi-Finder
** • Make caches non-purgeable
** • Try for System Heap
** • Failure: Try for Application memory.
** • Failure: Make caches purgeable and try again from the top.
** (Better)Selectively choose caches for purgeability.
** Finder
** • Make caches non-purgeable
** • Try for Application memory.
** • Failure: Make caches purgeable and try again from the top.
** (Better)Selectively choose caches for purgeability.
** No luck -
** • Return nil
**
** Under 7.0 NCH looks in temp mem first, bracketing the call with sysmode
** What is this bracketing magic???
**
** Allocate in non app heap with no purge
** Allocate in App heap with purge
** Allocate in Multi heap with purge
**
** New stuff:
** • Allocate in non-app heap (sys or multi) until full with no purge
** • Allocate in app heap until full with no purge
** • Switch back and forth with purge on
*/
Handle sb_NewZoneHandle(sb_SplineKeyHdl splineKey, long size, THz* zone)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register Handle h = nil;
THz curZone = GetZone();
THz savedZone;
Boolean sameAppZone;
savedZone = curZone;
if ( splineKeyPtr->curAppZone == SystemZone( ) )
splineKeyPtr->curAppZone = nil;
if ( curZone == SystemZone( ) ) {
curZone = splineKeyPtr->curAppZone;
if ( curZone == nil )
curZone = ApplicZone( );
}
SetZone( curZone );
sameAppZone = (splineKeyPtr->curAppZone == curZone);
if (!sameAppZone){
splineKeyPtr->curAppZone = curZone; /* log current zone */
splineKeyPtr->appFull = false; /* Reset for different zone */
}
if (!splineKeyPtr->appFull) { /* <30-CEL> */
sb_SetCachesNoPurge();
if (splineKeyPtr->mfExists && !splineKeyPtr->sysFull) {
h = sb_GetSysHandleZone(size, zone);
if (!h) {
splineKeyPtr = *splineKey;
splineKeyPtr->sysFull = true;
}
}
if (!h) {
h = sb_GetAppHandleZone(size, zone);
if (!h) {
splineKeyPtr = *splineKey;
splineKeyPtr->appFull = true;
}
}
sb_SetCachesPurge();
}
if (!h) { /* Full with no purge on so try without it */
if (splineKeyPtr->useHeap == useApp) {
h = sb_GetAppHandleZone(size, zone);
if (!h) h = sb_GetSysHandleZone(size, zone);
splineKeyPtr = *splineKey;
splineKeyPtr->useHeap = useSys;
} else {
h = sb_GetSysHandleZone(size, zone);
if (!h) h = sb_GetAppHandleZone(size, zone);
splineKeyPtr = *splineKey;
splineKeyPtr->useHeap = useApp;
}
}
SetZone( savedZone );
return h;
} /* End sb_NewZoneHandle */
/*********************************************************************************************
** sb_NewSharedHandle <30-CEL> new routine
**
** This data will be shared across heaps in Multi-Finder mode so it must be in the system heap.
** Otherwise under finder just put it in the app heap since it will not be multiply shared.
** Finder Mode: Application Heap
** Multi Finder: System Heap (Shared)
**
*/
Handle sb_NewSharedHandle(sb_SplineKeyHdl splineKey, long cacheSize)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register Handle h = nil;
if (splineKeyPtr->mfExists) {
if (!splineKeyPtr->appFull && !splineKeyPtr->sysFull) {
sb_SetCachesNoPurge(); /* <30-CEL> */
h = sb_GetSysHandle(cacheSize); /* system heap mem */
sb_SetCachesPurge();
if (!h) {
splineKeyPtr = *splineKey;
splineKeyPtr->sysFull = true;
}
}
if (!h) h = sb_GetSysHandle(cacheSize); /* system heap mem */
} else {
THz curZone = GetZone();
Boolean sameAppZone = (splineKeyPtr->curAppZone == curZone);
if (!sameAppZone){
splineKeyPtr->curAppZone = curZone; /* log current zone */
splineKeyPtr->appFull = false; /* Reset for different zone */
}
if (!splineKeyPtr->appFull) {
sb_SetCachesNoPurge(); /* <30-CEL> */
h = sb_GetAppHandle(cacheSize); /* <28-CEL> Try the App Heap */
sb_SetCachesPurge();
if (!h) {
splineKeyPtr = *splineKey;
splineKeyPtr->appFull = true;
}
}
if (!h) h = sb_GetAppHandle(cacheSize); /* app heap mem */
}
return h;
} /* End sb_NewSharedHandle */
/*********************************************************************************************
** sb_GrowHandle <28-CEL> new routine
**
** Grow the current shared data block handle…
** If this is in the App heap make sure there is enough space before requesting
** the memory. Otherwise this could cause the Application purge proc to be called
** and the App might exit with an out of memory.
**
** If in the Multi Heap try with no purgeability.
** Fails: try with purgeability
**
** App heap always try with purgeability.
**
*/
long sb_GrowHandle(sb_SplineKeyHdl splineKey, Handle h, long size)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register long result = NO_ERR;
THz curZone = GetZone();
Boolean sameAppZone = (splineKeyPtr->curAppZone == curZone);
if (!sameAppZone) {
splineKeyPtr->curAppZone = curZone; /* log current zone */
splineKeyPtr->appFull = false; /* Reset for different zone */
}
if (HandleZone(h) != curZone) { /* <30-CEL> sys heap */
if (!splineKeyPtr->appFull) { /* <30-CEL> */
sb_SetCachesNoPurge(); /* <30-CEL> */
SetHandleSize(h, size); /* <30-CEL> took out set and restore zone for sethandlesize */
result = MemError(); /* <30-CEL> */
sb_SetCachesPurge(); /* <30-CEL> */
if (result) {
SetHandleSize(h, size); /* <30-CEL> took out set and restore zone for sethandlesize */
result = MemError(); /* <30-CEL> */
}
} else {
SetHandleSize(h, size); /* <30-CEL> took out set and restore zone for sethandlesize */
result = MemError(); /* <30-CEL> */
}
} else { /* <30-CEL> app heap */
if (!splineKeyPtr->appFull) {
sb_SetCachesNoPurge(); /* <30-CEL> */
result = sb_GrowAppHandle(h, size);
sb_SetCachesPurge();
if (result) {
result = sb_GrowAppHandle(h, size);
splineKeyPtr = *splineKey;
splineKeyPtr->appFull = true;
}
} else result = sb_GrowAppHandle(h, size);
}
return result;
} /* End sb_GrowHandle */
/*********************************************************************************************
** sb_SizeTheBlock <28-CEL> some logic
**
** Block exist: Resize handle… if this fails, get new one, copy over data if needed, and dipose old one.
** Empty or purged Handle: Dipose if handle is purged but exists and then get brand new one.
**
** Upfront we will try to keep existing caches. If memory allocations fail try again with purgeable
** caches.
**
** If it is the App heap, make sure there is enough contiguous space to make the request.
** If this is not done, it could cause the applicaton purge proc to be called and it could
** cause a out of memory error.
**
** MERGE comments from sb_GrowZoneHandle…
** Block exist: Resize handle… if this fails, get new one, copy over data if needed, and dipose old one.
** Empty or purged Handle: Dispose if handle is purged but exists and then get brand new one.
**
** Upfront we will try to keep existing caches. If memory allocations fail try again with purgeable
** caches.
**
** CachePlace:
** • When a cacheHandle is moved via a newHandle of somekind the cacheHandle inside the
** cacheList must be updated. Use CachePlace to find the correct cache info inside the
** the cache list.
** • if cachePlace == -1, ignore the update. This means it is not a cacheChunk.
**
*/
Handle sb_SizeTheBlock(sb_SplineKeyHdl splineKey, Handle inputH, THz* inputZone, long inputSize,
ZoneHandleOptions options, short cachePlace, ShrinkOptions shrinkTest)
{
register Handle h = inputH; /* <28-CEL> */
register THz *zone = inputZone; /* <28-CEL> */
register long size = inputSize; /* <28-CEL> */
Boolean room = true;
if (h) { /* <28-CEL> */
if (*h) { /* <28-CEL> */
if (shrinkTest == noShrink && size <= GetHandleSize(h)) return h; /* <30-CEL> Right size… leave it alone */
if (!sb_GrowHandle(splineKey, h, size)) return h; /* <30-CEL> */
/* THIS SHOULD BE A RARE CASE!!! */
/* If we get this far, growing the existing handle failed, so allocate a new one */
if (options & kKeepContents) {
register long origSize = GetHandleSize(h); /* <28-CEL> */
THz newZ;
Handle newH;
short handState = HGetState(h);
if (newH = sb_NewZoneHandle(splineKey, size, &newZ)) {
BlockMove( *h, *newH, origSize );
sb_DisposeZoneHandle( h, *zone ); /* <28-CEL> assigned zone before disposing caused problems */
if (cachePlace != -1) { /* <28-CEL> Need to update cache info in cacheList */
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register CacheReference *cacheR = *splineKeyPtr->cacheListHandle + splineKeyPtr->cachePlace; /* <28-CEL> */
cacheR->cache = newH; /* <28-CEL> */
cacheR->zone = newZ; /* <28-CEL> */
}
*zone = newZ; /* <28-CEL> */
HSetState(newH,handState); /* <31-CEL> set to original state */
return newH;
} else return nil;
}
} else { /* ERROR!!!: This routine should never be called with a purged handle!!! */
sb_Debug(); /* <27-CEL> */
return nil; /* <27-CEL> */
}
}
return(sb_NewZoneHandle( splineKey, size, zone ));
} /* End sb_SizeTheBlock */
/*********************************************************************************************
** sb_ModCacheList
**
** sb_ModCacheList increases the number of nil cache_head entries in the cacheListHandle.
** either it grows cacheListHandle by GROW_CACHE_NUM
** or if cacheListHandle is nil, it allocates INITIAL_CACHES entries
**
** Finder Mode:
** CacheListHand lives in the App Heap
** Multi Mode:
** CacheListHand lives in the Sys Heap
**
*/
static long sb_ModCacheList(sb_SplineKeyHdl splineKey)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register short newFontCount;
register long cacheSize;
register short initCount;
long result = NO_ERR;
register Handle tempHand = nil;
if (splineKeyPtr->cacheListHandle) {
register Handle h = splineKeyPtr->cacheListHandle;
THz zone = HandleZone(h);
newFontCount = splineKeyPtr->fontCount + GROW_CACHE_NUM;
initCount = GROW_CACHE_NUM;
cacheSize = GetHandleSize(h) + GROW_CACHE_NUM * sizeof(CacheReference);
result = sb_GrowHandle(splineKey, h, cacheSize); /* <30-CEL> */
} else {
splineKeyPtr->fontCount = 0;
newFontCount = initCount = INITIAL_CACHES;
cacheSize = INITIAL_CACHES * sizeof(CacheReference);
tempHand = NewHandleSys( cacheSize );
if (tempHand) { /* <30-CEL> */
splineKeyPtr = *splineKey;
splineKeyPtr->cacheListHandle = (CacheReference**)tempHand; /* <30-CEL> */
} else
result = NEWCACHELIST_HANDLE_ERR; /* <30-CEL> */
} /* End If */
if (!result) {
register CacheReference* cacheR; /* <28-CEL> */
register Handle zero = 0;
splineKeyPtr = *splineKey;
cacheR = *splineKeyPtr->cacheListHandle + splineKeyPtr->fontCount;
for (--initCount; initCount >= 0; --initCount) { /* begin new caches as nil */
cacheR->cache = zero;
cacheR++;
}
splineKeyPtr->fontCount = newFontCount;
}
return result; /* <27-CEL */
} /* End sb_ModCacheList */
/*******************************/
/** WRAPPERS For memory calls **/
/*******************************/
void sb_DisposeCacheHandle( Handle cacheHandle, THz cacheZone )
{
DumpFontCacheToDiskIfNotTooBig( (sb_CacheHeadHdl) cacheHandle );
sb_DisposeZoneHandle( cacheHandle, cacheZone );
}
/*********************************************************************************************
** sb_DisposeWorkHandle <28-CEL> a little comment
**
** If a handle is purged and the zone from which the handle came from is not the current zone,
** the memory manager does not know where to link the free handle. This is bad news unless
** we switch to the correct zone and then dispose of the handle!
**
*/
void sb_DisposeWorkHandle() /* <28-CEL> took out splineKeyPtr param to make code consistent */
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
if (splineKeyPtr->fsWorkHand) { /* <28-CEL> */
sb_DisposeZoneHandle(splineKeyPtr->fsWorkHand, splineKeyPtr->fsWorkZone);
splineKeyPtr->fsWorkHand = 0;
splineKeyPtr->fsWorkZone = 0; /* <28-CEL> */
}
}
/*********************************************************************************************
** sb_SizeWorkHandle <28-CEL>
**
** Size the Font Scaler work space. If it does not exist it will
** create one.
**
** ZoneHandleOptions: Sets state if the memory needs to be preserved.
** letShrink: Set if memory should be shrunk.
**
*/
long sb_SizeWorkHandle( long size, ZoneHandleOptions zOptions, ShrinkOptions shrinkTest )
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register Handle h = splineKeyPtr->fsWorkHand; /* <28-CEL> */
THz z; /* <28-CEL> */
register long result = NO_ERR; /* <28-CEL> */
if (h && !*h) sb_DisposeWorkHandle(); /* <31-CEL> */
z = splineKeyPtr->fsWorkZone; /* <28-CEL> */
h = splineKeyPtr->fsWorkHand; /* <28-CEL> */
if (h = sb_SizeTheBlock( splineKey, h, &z, size, zOptions, -1, shrinkTest )) {
splineKeyPtr = *splineKey; /* <28-CEL> */
splineKeyPtr->fsWorkHand = h; /* <28-CEL> */
splineKeyPtr->fsWorkZone = z; /* <28-CEL> */
} else {
result = MEM_ERR;
}
return result;
} /* End sb_SizeWorkHandle */
/*********************************************************************************************
** sb_GetBitMapSpace <28-CEL> rewrote
**
** This is a temporary bitmap to blit in when the glyph is not cached.
**
*/
static Handle sb_GetBitMapSpace(register long bmSize)
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register Handle h = splineKeyPtr->bitmapHand; /* <28-CEL> */
THz z;
register long result = NO_ERR;
if (h && !*h) { /* purged so get rid of it and start over */ /* <28-CEL> */
sb_DisposeZoneHandle(h, splineKeyPtr->bitmapZone); /* <28-CEL> */
splineKeyPtr->bitmapHand = 0; /* <28-CEL> */
splineKeyPtr->bitmapZone = 0; /* <28-CEL> */
}
z = splineKeyPtr->bitmapZone; /* <28-CEL> */
if (h = sb_SizeTheBlock( splineKey, splineKeyPtr->bitmapHand, &z, bmSize, kNoOptions, -1, doShrink )) { /* <28-CEL> */
splineKeyPtr = *splineKey; /* <28-CEL> */
splineKeyPtr->bitmapZone = z; /* <28-CEL> */
splineKeyPtr->bitmapHand = h;
}
return h; /* <28-CEL> */
} /* End sb_GetBitMapSpace */
/*********************************************************************************************
** sb_BandChar
**
**
*/
Handle sb_BandChar(sb_SplineKeyHdl splineKey, short *scan, short byteWidth, long memForScanLine)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register Handle tempHand;
long sizeOfMem6;
for ((*scan) >>= 1;*scan >= 1;(*scan) >>= 1) {
sizeOfMem6 = (long)LONG_WORD_ALIGN((*scan * memForScanLine)); /* divide by 2 */
if (!sb_SizeWorkHandle((*splineKey)->rowArrayOffset6+sizeOfMem6, kKeepContents, doShrink)) {
if (tempHand = sb_GetBitMapSpace(*scan * byteWidth))
return tempHand;
}
}
return 0;
} /* End sb_BandChar */
/**********************/
/** END MEMORY CALLS **/
/**********************/
/***********************************************************************************************/
/***********************************************************************************************/
/***********************************************************************************************/
/********************/
/* SET UP AND CACHE */
/********************/
/*********************************************************************************************
** sb_ResetFSWorkState
**
** Reset the SplineKey Font Scaler state.
**
**
*/
sb_ResetFSWorkState(sb_SplineKeyPtr splineKeyPtr)
{
register sb_SplineKeyPtr skPtr = splineKeyPtr;
skPtr->StrikeID = -1;
skPtr->ptSize = 0;
skPtr->device = 0;
skPtr->face = 0;
skPtr->trans00 = -1;
skPtr->trans11 = -1;
skPtr->trans10 = -1;
} /* End sb_ResetFSWorkState */
/*********************************************************************************************
** sb_SetMemPtrs
**
** sb_SetMemPtrs
**
** Usage: Called once to set up spline package vectors and init the workspace.
**
** Notes: memory [5] points to bitmap hand
*
* Assumes that fsWorkHand is NOT purged or empty
**
*/
static void sb_SetMemPtrs( widthTableHdl widthTableHandle )
{
register sb_SplineKeyPtr splineKeyPtr = *(SPLINE_KEY_HAND);
char *memoryPtr = *splineKeyPtr->fsWorkHand;
register char** memBase; /*<16> increment ptr instead of array */
splineKeyPtr->inPtr = (fs_GlyphInputType *)(memoryPtr + splineKeyPtr->inputOffset);
splineKeyPtr->outPtr = (fs_GlyphInfoType *)(memoryPtr + splineKeyPtr->infoOffset);
memBase = (*splineKeyPtr->inPtr).memoryBases;
*memBase++ = memoryPtr + splineKeyPtr->globalOffset0; /* memoryBases[0] */
*memBase++ = memoryPtr + splineKeyPtr->globalOffset1; /* memoryBases[1] */
*memBase++ = memoryPtr + splineKeyPtr->globalOffset2; /* memoryBases[2] */
*memBase++ = memoryPtr + splineKeyPtr->sfntDataOffset3; /* memoryBases[3] */
*memBase++ = memoryPtr + splineKeyPtr->sfntDataOffset4; /* memoryBases[4] */
memBase++; /* memoryBases[5] */
*memBase++ = memoryPtr + splineKeyPtr->rowArrayOffset6; /* memoryBases[6] */
*memBase = memoryPtr + splineKeyPtr->columnArrayOffset7; /* memoryBases[7] */
(*splineKeyPtr->inPtr).sfntDirectory = (widthTableHandle == nil) ? nil : (int32*) (*widthTableHandle)->fSplineDirectory;
} /* End sb_SetMemPtrs */
/*********************************************************************************************
** sb_CheckWorkHandle <28-CEL> new routine
**
** Check to see if the workhandle exists. If it does then just return, otherwise re-establish.
**
*/
long sb_CheckWorkHandle()
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register Handle h = splineKeyPtr->fsWorkHand;
register long result = NO_ERR;
if (!h || !*h) {
long position = 0;
short splineKeyState = HGetState((Handle)splineKey);
register char *memoryPtr;
HLock((Handle)splineKey);
splineKeyPtr->inputOffset = position;
position += LONG_WORD_ALIGN(sizeof(fs_GlyphInputType));
splineKeyPtr->infoOffset = position;
position += LONG_WORD_ALIGN( sizeof(fs_GlyphInfoType));
if (!(result = sb_SizeWorkHandle(position, kNoOptions, noShrink))) {
memoryPtr = *splineKeyPtr->fsWorkHand;
splineKeyPtr->inPtr = (fs_GlyphInputType *)(memoryPtr + splineKeyPtr->inputOffset);
splineKeyPtr->outPtr = (fs_GlyphInfoType *)(memoryPtr + splineKeyPtr->infoOffset);
(*splineKeyPtr->inPtr).GetSfntFragmentPtr = (GetSFNTFunc)QDGetFontFrag;
(*splineKeyPtr->inPtr).ReleaseSfntFrag = (ReleaseSFNTFunc)QDUngetFontFrag;
/* reinitialize the state to make sure the FS gets ran through */
sb_ResetFSWorkState(splineKeyPtr);
if (!(result = fs_OpenFonts( splineKeyPtr->inPtr, splineKeyPtr->outPtr ))) {
/*******************/
/* SETTING OFFSETS */
/*******************/
splineKeyPtr->globalOffset0 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[0]);
splineKeyPtr->globalOffset1 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[1]);
splineKeyPtr->globalOffset2 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[2]);
splineKeyPtr->sfntDataOffset3 = position;
/*******************/
/***********************/
/** FSWorkHand HANDLE **/
/***********************/
if (!(result = sb_SizeWorkHandle( position, kKeepContents, noShrink ))) {
sb_SetMemPtrs(0);
if (result = fs_Initialize( splineKeyPtr->inPtr, splineKeyPtr->outPtr ))
sb_Debug();
}
} else sb_Debug();
if (result) sb_DisposeWorkHandle(); /* failed so get rid of state */
}
HSetState((Handle)splineKey, splineKeyState);
}
return result;
} /* End sb_CheckWorkHandle */
/*********************************************************************************************
** sb_ShrinkBitmap
**
** The scan converted bitmap can have extra space at the end of it so shrink down to get rid
** of the excess.
**
**
*/
static void sb_ShrinkBitmap( sb_GlyphData *glyphDataPtr, long *bitMapPtr, short inputScan )
{
register short bitWidth = glyphDataPtr->bitWidth;
register short scan = inputScan - 1;
short scanByteWidth = glyphDataPtr->scanByteWidth;
/*************************/
/* Shrinking down the bitmap
** 16-bit or less -> word
** 32-bit or less -> long
** > 32-bit -> multiple of longs
*/
if (bitWidth <= 16) { /*<16> fast scan-loop */
register short *src, *dest;
src = dest = (short *)bitMapPtr;
for (; scan >= 0; --scan) {
*dest++ = *src++;
src++; /* next src row */
}
glyphDataPtr->byteWidth = 2;
} else { /*<16> fast scan-loops, set src and dest once */
register long *src, *dest;
src = dest = (long *)bitMapPtr;
if (bitWidth <= 32) {
if (scanByteWidth > 4) { /* Sampo uses two longs even though bitwidth is only 32 */
for (; scan >= 0; --scan) {
*dest++ = *src++;
src++; /* next src row */
}
glyphDataPtr->byteWidth = 4;
}
} else { /*<16> fast j-loop */
register short numOfLongs = ((bitWidth + 31) >> 5); /* number of longs truely needed */
if (numOfLongs > (scanByteWidth >> 2)) { /* Sampo uses an extra long if last whole long is used */
register short j;
--numOfLongs; /* save decrement in j-loop */
for (; scan >= 0; --scan) {
for (j = numOfLongs; j >= 0; --j)
*dest++ = *src++;
src++; /* next src row */
}
numOfLongs++; /* restore to orig value */
glyphDataPtr->byteWidth = numOfLongs << 2; /* turn to bytes */
}
}
}
} /* End sb_ShrinkBitmap */
/*********************************************************************************************
** sb_SetFontMemory
**
** Note on 6/19/92 change. This routine formerly called GetEncodingTable to get the script.
** the funny thing about that is that GetEncodingTable's primary raison d'etre is to return
** a table of booleans used to distinguish high and low bytes in a CJK font. It also
** happened to return the script of the encoding table returned. Well, until now if
** the FOND ID being passed in wasn't an ID for a CJK font then GetEncodingTable returned
** roman. This tended to make international fonts with correctly coded cmap tables not
** work at all. The first thing I did was change GetEncodingTable to return the correct value
** However, I've rethought the wisdom of calling a routine primarily designed for CJK and have
** changed this routine (which never really cared about encoding tables) to call the more generic
** script manager trap Font2RealScript. The change to GetEncodingTable was left in though.
*/
static long sb_SetFontMemory(sb_SplineKeyHdl splineKey, widthTableHdl widthTableHandle )
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register long result = NO_ERR;
register long position;
uint16 scriptID;
sb_SetMemPtrs(widthTableHandle);
//GetEncodingTable( splineKeyPtr->fLastSwapFontFamilyID, &scriptID );
scriptID = Font2RealScript( splineKeyPtr->fLastSwapFontFamilyID );
(*splineKeyPtr->inPtr).param.newsfnt.platformID = 1;
(*splineKeyPtr->inPtr).param.newsfnt.specificID = scriptID;
result = __NewSfntTrap(splineKeyPtr->inPtr, splineKeyPtr->outPtr); //<22>
if ( result ) {
if ( scriptID != smRoman ) { //we tried for a script this might be an old font so let's try Roman
(*splineKeyPtr->inPtr).param.newsfnt.platformID = 1;
(*splineKeyPtr->inPtr).param.newsfnt.specificID = smRoman;
result = __NewSfntTrap(splineKeyPtr->inPtr, splineKeyPtr->outPtr); //<22>
}
//
//test result again, if still non-zero that is it for us, if it is 0 we fall throught and set up
//memory.
//
if ( result ) {
sb_Debug();
return result;
}
}
position = splineKeyPtr->sfntDataOffset3;
position += LONG_WORD_ALIGN( (*splineKeyPtr->outPtr).memorySizes[3]);
splineKeyPtr->sfntDataOffset4 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[4]);
splineKeyPtr->rowArrayOffset6 = position;
splineKeyPtr->columnArrayOffset7 = position;
if (result = sb_SizeWorkHandle( position, kKeepContents, noShrink )) return MEM_ERR;
return result;
}
/*********************************************************************************************
** sb_SetNewSFNT
**
** If the sfnt has changed, reset the FontScaler environment.
**
** Logic:
** • Font change: run fs_NewSfnt and fs_NewTransformation
** • ptSize or transformation changed : run fs_NewTransformation
**
**
*/
static long sb_SetNewSFNT( widthTableHdl widTabHand )
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register widthTablePtr widTabPtr = *widTabHand;
register long result = NO_ERR;
short doNewTrans = false;
sb_SetMemPtrs(widTabHand);
(*splineKeyPtr->inPtr).clientID = widTabPtr->tabFont; /* Always reset because the memory environment may have changed */
if ( splineKeyPtr->StrikeID != widTabPtr->StrikeID ) {
if (result = sb_SetFontMemory(splineKey, widTabHand)) return MEM_ERR;
splineKeyPtr = *splineKey;
widTabPtr = *widTabHand;
doNewTrans = true;
splineKeyPtr->StrikeID = widTabPtr->StrikeID;
}
if ( doNewTrans ||
splineKeyPtr->ptSize != widTabPtr->fSize ||
splineKeyPtr->trans00 != widTabPtr->trans00 ||
splineKeyPtr->trans11 != widTabPtr->trans11 ||
splineKeyPtr->trans10 != widTabPtr->trans10
) {
register fs_GlyphInputType* fsInput;
transMatrix matrix; /* this could be a global matrix */
matrix.transform[2][0] = 0;
matrix.transform[0][1] = 0;
matrix.transform[2][1] = 0;
matrix.transform[0][2] = 0;
matrix.transform[1][2] = 0;
matrix.transform[2][2] = (1L << 30);
matrix.transform[0][0] = widTabPtr->trans00;
matrix.transform[1][1] = widTabPtr->trans11;
matrix.transform[1][0] = widTabPtr->trans10;
sb_SetMemPtrs(widTabHand);
fsInput = splineKeyPtr->inPtr;
fsInput->param.newtrans.transformMatrix = &matrix;
fsInput->param.newtrans.pointSize = (Fixed)widTabPtr->fSize << 16;
fsInput->param.newtrans.xResolution = POINTSPERINCH;
fsInput->param.newtrans.yResolution = POINTSPERINCH;
fsInput->param.newtrans.pixelDiameter = FIXEDSQRT2;
fsInput->param.newtrans.traceFunc = 0;
#if TheFuture /* <18 > EBITMAP */
fsInput->param.newtrans.bitmapMethodPreferences = 1;
fsInput->param.newtrans.scalingPreference = 0;
#endif
if ( result = fs_NewTransformation( splineKeyPtr->inPtr, splineKeyPtr->outPtr ) ) {
splineKeyPtr->ptSize = 0;
splineKeyPtr->trans00 = 0;
splineKeyPtr->trans11 = 0;
splineKeyPtr->trans10 = 0;
sb_Debug();
return result;
}
splineKeyPtr->ptSize = widTabPtr->fSize;
splineKeyPtr->trans00 = widTabPtr->trans00;
splineKeyPtr->trans11 = widTabPtr->trans11;
splineKeyPtr->trans10 = widTabPtr->trans10;
} /* End If */
return NO_ERR;
} /* End sb_SetNewSFNT */
/*
* Returns the font's real style, ignoring any algorithmic effects
*/
short IntrinsicStyle(widthTablePtr w)
{
return (w->face >> 8) & ~w->aFace;
}
/*********************************************************************************************
** sb_InitCacheHead
**
** Initialize the cacheHead with the widthTable information.
**
**
**
*/
static long sb_InitCacheHead(widthTableHdl widthTabHand, sb_CacheHeadHdl cacheHand )
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register widthTablePtr widTabPtr = *widthTabHand;
sb_SplineKeyPtr splineKeyPtr = *splineKey; /*<16> removed register */
register sb_CacheHeadPtr cachePtr = *cacheHand;
char *hiliteModePtr = HILITEMODE;
long result = NO_ERR;
cachePtr->familyID = (*splineKey)->fLastSwapFontFamilyID;
cachePtr->StrikeID = widTabPtr->StrikeID;
cachePtr->ptSize = widTabPtr->fSize;
cachePtr->face = IntrinsicStyle(widTabPtr);
cachePtr->squashed = !(*hiliteModePtr & PRESERVE_GLYPH);
cachePtr->trans00 = widTabPtr->trans00;
cachePtr->trans11 = widTabPtr->trans11;
cachePtr->trans10 = widTabPtr->trans10;
cachePtr->bitsCached = widTabPtr->aSize <= MAX_PPEM_CACHED;
cachePtr->addEntryOffset = (GLYPH_COUNT * sizeof(long)) + sizeof(sb_CacheHead);
cachePtr->fEncodingTablePointer = (Ptr) GetEncodingTable( (*splineKey)->fLastSwapFontFamilyID, &cachePtr->fScriptNumber );
sb_SetMemPtrs(widthTabHand);
result = fs_FillLayoutInfo( splineKeyPtr->inPtr, splineKeyPtr->outPtr, (fs_LayoutInfo *)&cachePtr->ascent );
if (!result) {
if (cachePtr->trans10 /*OBLIQUE*/) { /* If oblique changes change this slop adjust */
if (widTabPtr->aSize <= 8) {
cachePtr->rightItalicSlop = (cachePtr->ascent / 2);
cachePtr->leftItalicSlop = (cachePtr->descent / 2);
} else if (widTabPtr->aSize <= 16) {
cachePtr->rightItalicSlop = (cachePtr->ascent / 3);
cachePtr->leftItalicSlop = (cachePtr->descent / 3);
} else if (widTabPtr->aSize <= 22) {
cachePtr->rightItalicSlop = (cachePtr->ascent / 4);
cachePtr->leftItalicSlop = (cachePtr->descent / 4);
} else {
cachePtr->rightItalicSlop = (cachePtr->ascent / 5);
cachePtr->leftItalicSlop = (cachePtr->descent / 5);
}
} else {
cachePtr->rightItalicSlop = 0;
cachePtr->leftItalicSlop = 0;
}
/********************/
/* Round to ceiling */
/********************/
/*<16> put masks into registers */
{
Fixed lowordmask = 0x0000FFFF;
Fixed hiwordmask = 0xFFFF0000;
cachePtr->ascent = (cachePtr->ascent + lowordmask) & hiwordmask;
cachePtr->descent = (-cachePtr->descent + lowordmask) & hiwordmask;
if ( (*hiliteModePtr & PRESERVE_GLYPH) ) {
cachePtr->yMax = (cachePtr->yMax + lowordmask) & hiwordmask;
cachePtr->yMin = (cachePtr->yMin - lowordmask) & hiwordmask;
} else {
cachePtr->yMax = cachePtr->ascent;
cachePtr->yMin = -cachePtr->descent;
}
cachePtr->height = (short)((cachePtr->yMax - cachePtr->yMin) >> 16);
cachePtr->widMax = (cachePtr->widMax + lowordmask) & hiwordmask;
cachePtr->leading = (cachePtr->leading + lowordmask) & hiwordmask;
cachePtr->lOverHMax = (cachePtr->lOverHMax + lowordmask) & hiwordmask;
cachePtr->rOverHMax = (cachePtr->rOverHMax + lowordmask) & hiwordmask;
cachePtr->leftItalicSlop = -((cachePtr->leftItalicSlop + lowordmask) & hiwordmask);
cachePtr->rightItalicSlop = (cachePtr->rightItalicSlop + lowordmask) & hiwordmask;
cachePtr->fmAscent = ByteMax(cachePtr->ascent);
cachePtr->fmDescent = ByteMax(cachePtr->descent);
cachePtr->fmWidMax = ByteMax(cachePtr->widMax);
cachePtr->fmLeading = ByteRange(cachePtr->leading);
}
/********************/
}
/*<16> fast loop, local i, initArrayPtr */
{
register long* initArrayPtr = (long*)cachePtr->glyphArray;
register short i = GLYPH_COUNT - 1;
for (; i >= 0; --i)
*initArrayPtr++ = EMPTY;
}
return result;
} /* End sb_InitCacheHead */
/*********************************************************************************************
** sb_ShrinkCacheToMin <3-CEL>
**
** Low on memory so shrink the cache to a minimum and initialize new state.
**
**
** AddEntryOffset = 0: Do not copy glyph entry.
**
*/
long sb_ShrinkCacheToMin(sb_CacheHeadHdl cacheHand, long addEntryOffset)
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
sb_SplineKeyPtr splineKeyPtr = *splineKey;
sb_CacheHeadPtr cachePtr = *cacheHand;
register long entryArraySize = (GLYPH_COUNT * sizeof(long));
register long* initArrayPtr = cachePtr->glyphArray;
long result = NO_ERR;
register short i;
register long *oldGDataPtr;
register long *newGDataPtr;
/* new start for add entry */
cachePtr->addEntryOffset = entryArraySize + sizeof(sb_CacheHead);
if (addEntryOffset) {
oldGDataPtr = (long *)((char *)cachePtr + addEntryOffset);
newGDataPtr = (long *)((char *)cachePtr + cachePtr->addEntryOffset);
i = (GLYPH_HEAD_BYTES>>2); /* longs to copy */
for (--i; i >= 0; --i)
*newGDataPtr++ = *oldGDataPtr++;
}
for (i=GLYPH_COUNT-1; i >= 0; --i)
*initArrayPtr++ = EMPTY;
SetHandleSize((Handle)cacheHand, sizeof(sb_CacheHead) + entryArraySize + GLYPH_HEAD_BYTES);
if (!(result = MemError()))
result = sb_SizeWorkHandle((*splineKey)->rowArrayOffset6, kKeepContents, doShrink); /* <8-CEL,RB> */
return result;
} /* End sb_ShrinkCacheToMin */
/*********************************************************************************************
** sb_FigureCacheSize
**
** Takes the current WidthTable and calculates the initial cache size needed.
**
** Make it the minimum of the cache header and enough room for one entry header.
**
*/
static long sb_FigureCacheSize(widthTableHdl widthTabHand)
{
register widthTablePtr widTabPtr = *widthTabHand;
register long entryArraySize = (GLYPH_COUNT * sizeof(long));
register long cacheSize = 0;
Boolean bitsCached = widTabPtr->aSize < MAX_PPEM_CACHED;
cacheSize = sizeof(sb_CacheHead) + GLYPH_HEAD_BYTES; /* <34-CEL> */
#ifdef LEAVE_OUT /* <33-CEL> forget about room for characters for now */
if ( bitsCached )
cacheSize += (widTabPtr->aSize / 8) * widTabPtr->aSize * INITIAL_CHAR_COUNT;
else cacheSize += AVG_CONTOUR_SIZE * INITIAL_CHAR_COUNT;
#endif
cacheSize += entryArraySize; /* Add glyph array */
cacheSize += 3; cacheSize &= ~3; /* Start Long word aligned */
return cacheSize;
} /* End sb_FigureCacheSize */
/*********************************************************************************************
** sb_ResetHeapState
**
**
**
*/
void sb_ResetHeapState( sb_SplineKeyPtr splineKeyPtr )
{
register sb_SplineKeyPtr sPtr = splineKeyPtr;
sPtr->curAppZone = 0; /* <30-CEL> */
sPtr->appFull = false; /* <30-CEL> */
sPtr->sysFull = false; /* <30-CEL> */
sPtr->useHeap = useApp; /* <30-CEL> */
} /* End sb_ResetHeapState */
/*********************************************************************************************
** sb_FlushFonts
**
** sb_FlushFonts
**
**
*/
pascal OSErr sb_FlushFonts()
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
sb_SplineKeyPtr splineKeyPtr = *splineKey;
long* lastSpExtrPtr = LASTSPEXTRA;
*lastSpExtrPtr = 0xFFFFFFFF;
if (splineKeyPtr->cacheListHandle) {
register short fontCount = splineKeyPtr->fontCount;
register CacheReference* cacheRef = *splineKeyPtr->cacheListHandle;
register Handle zero = 0;
for (--fontCount; fontCount >= 0; --fontCount) {
if (cacheRef->cache) {
sb_DisposeCacheHandle(cacheRef->cache, cacheRef->zone);
cacheRef->cache = zero;
}
cacheRef++;
}
splineKeyPtr->cacheHand = 0; /* <28-CEL> */
splineKeyPtr->cacheZone = 0; /* <28-CEL> */
splineKeyPtr->cachePlace = 0; /* <28-CEL> */
sb_DisposeZoneHandle((Handle)splineKeyPtr->cacheListHandle, /* <28-CEL> start over */
HandleZone((Handle)splineKeyPtr->cacheListHandle));
splineKeyPtr->cacheListHandle = 0;
}
sb_DisposeWorkHandle(); /* <28-CEL> */
/* Dispose of all fragment table caches */
KillApplicationHeapFragmentTableCaches( (Handle) 0, (Handle) 0x7fffffff );
/* Reset since the heaps have changed */
sb_ResetHeapState(splineKeyPtr);
return NO_ERR;
} /* End sb_FlushFonts */
/*********************************************************************************************
** sb_KillSomeCaches
**
** Clean up caches in the current heap that is going away. If the cachelisthandle is going
** away, throw away the caches and get rid of the cachelisthandle. Make sure to get rid of
** any blocks that are in this heap also like the fsWorkHand.
**
**
*/
pascal long sb_KillSomeCaches( Handle inputStartAddr, Handle inputEndAddr )
{
register sb_SplineKeyPtr splineKeyPtr = *(SPLINE_KEY_HAND); /* <28-CEL> register */
register CacheReference* cacheR; /* <28-CEL> */
register short fontCount = splineKeyPtr->fontCount;
register Handle startAddr = inputStartAddr; /* <28-CEL> */
register Handle endAddr = inputEndAddr; /* <28-CEL> */
register Handle h; /* <28-CEL> */
if (splineKeyPtr->cacheListHandle) { /* <28-CEL> make sure it even exists */
cacheR = *splineKeyPtr->cacheListHandle; /* <28-CEL> */
h = (Handle)splineKeyPtr->cacheListHandle; /* <28-CEL> */
if (h >= startAddr && h < endAddr) { /* <28-CEL> cacheListHand in this heap clean all caches */
for (--fontCount; fontCount >= 0; --fontCount) { /* <28-CEL> */
if (cacheR->cache) sb_DisposeCacheHandle(cacheR->cache, cacheR->zone); /* <28-CEL> */
cacheR++; /* <28-CEL> */
}
sb_DisposeZoneHandle(h, HandleZone(h));
splineKeyPtr->cacheListHandle = 0; /* <28-CEL> */
splineKeyPtr->cacheHand = 0; /* <28-CEL> */
splineKeyPtr->cacheZone = 0; /* <28-CEL> */
splineKeyPtr->cachePlace = 0; /* <28-CEL> */
sb_ResetFSWorkState(splineKeyPtr);
} else {
for (--fontCount; fontCount >= 0; --fontCount) {
h = cacheR->cache; /* <28-CEL> */
if (h >= startAddr && h < endAddr) { /* <28-CEL> */
if (splineKeyPtr->cacheHand == h) { /* <28-CEL> */
splineKeyPtr->cacheHand = 0; /* <28-CEL> */
splineKeyPtr->cacheZone = 0; /* <28-CEL> */
splineKeyPtr->cachePlace = 0; /* <28-CEL> */
}
sb_DisposeCacheHandle( cacheR->cache, cacheR->zone );
cacheR->cache = 0;
cacheR->zone = 0; /* <28-CEL> */
}
cacheR++;
}
}
}
KillApplicationHeapFragmentTableCaches( startAddr, endAddr );
if ((h = splineKeyPtr->bitmapHand) && (h >= startAddr && h < endAddr)) { /* <28-CEL> */
sb_DisposeZoneHandle(h, splineKeyPtr->bitmapZone); /* <28-CEL> */
splineKeyPtr->bitmapHand = 0; /* <28-CEL> */
splineKeyPtr->bitmapZone = 0; /* <28-CEL> */
}
if ((h = splineKeyPtr->fsWorkHand) && (h >= startAddr && h < endAddr)) /* <28-CEL> */ /* <28-CEL> */
sb_DisposeWorkHandle(); /* <28-CEL> */
// <19> If FOND candidate lists are cached, flush them out too.
h = splineKeyPtr->fondCache[0]; // <19>
if (h) { // <19>
DisposeHandle(h); // <19>
splineKeyPtr->fondCache[0] = nil; // <19>
}
h = splineKeyPtr->fondCache[1]; // <19>
if (h) { // <19>
DisposeHandle(h); // <19>
splineKeyPtr->fondCache[1] = nil; // <19>
}
/* Reset since the heaps have changed */
sb_ResetHeapState(splineKeyPtr);
return NO_ERR;
} /* End sb_KillSomeCaches */
/*********************************************************************************************
** sb_CacheSFNTMatch
**
** Simply checks to see if the current widthtable request matches the cache found.
**
**
*/
Boolean sb_CacheSFNTMatch( sb_CacheHeadPtr cachePtr, widthTablePtr widTabPtr )
{
register sb_CacheHeadPtr cPtr = cachePtr; /* registers */
register widthTablePtr wtPtr = widTabPtr;
return(cPtr->StrikeID == wtPtr->StrikeID &&
cPtr->ptSize == wtPtr->fSize &&
cPtr->face == IntrinsicStyle(wtPtr) &&
cPtr->trans00 == wtPtr->trans00 &&
cPtr->trans11 == wtPtr->trans11 &&
cPtr->trans10 == wtPtr->trans10);
} /* End sb_CacheSFNTMatch */
/*********************************************************************************************
** sb_LoadNewCache
**
** On entry
** splineKeyPtr is locked
**
**
*/
long sb_LoadNewCache( sb_SplineKeyHdl splineKey, widthTableHdl widthTabHand, Boolean squashed )
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register CacheReference* cacheR = *splineKeyPtr->cacheListHandle;
register short i, fontCount = splineKeyPtr->fontCount;
register short cachePlace = -1;
long result = NO_ERR;
/* Search through the list of caches to see if we have a match */
for (i = 0; i < fontCount; i++) {
if (cacheR->cache && *cacheR->cache) {
sb_CacheHeadPtr cachePtr = (sb_CacheHeadPtr)*cacheR->cache;
if (sb_CacheSFNTMatch(cachePtr, *widthTabHand) && cachePtr->squashed == squashed) {
splineKeyPtr->cacheHand = (sb_CacheHeadHdl)cacheR->cache; /* <28-CEL> */
splineKeyPtr->cacheZone = cacheR->zone; /* <28-CEL> */
splineKeyPtr->cachePlace = i; /* <28-CEL> */
HNoPurge((Handle)splineKeyPtr->cacheHand); /* Current one is non-purgable */
break;
} /* End If */
} else if (cachePlace == -1)
cachePlace = i; /* remember first available (purged or gone) */
cacheR++;
} /* End For */
if (!splineKeyPtr->cacheHand) { /* no match, use cachePlace if valid */
THz zone; /* <28-CEL> just moved this above */
Handle cache; /* <28-CEL> just moved this above */
if (cachePlace == -1) { /* -1 means grow the cache */
cachePlace = splineKeyPtr->fontCount; /* first available of new caches */
if ( sb_ModCacheList(splineKey) ) { /* add more cache heads if needed */
cachePlace = 1;
}
} /* End If */
cacheR = *splineKeyPtr->cacheListHandle + cachePlace; /* <28-CEL> */
zone = cacheR->zone;
if (cacheR->cache && !*cacheR->cache) { /* <28-CEL> been purged so get rid of it and start over */
sb_DisposeZoneHandle( cacheR->cache, zone );
cacheR->cache = 0;
cacheR->zone = 0;
}
result = LoadFontCacheFromDisk( (sb_CacheHeadHdl*) &cache, &zone, widthTabHand, squashed );
cacheR = *splineKeyPtr->cacheListHandle + cachePlace;
if ( (result == noErr) && (cache != nil) ) {
cacheR->cache = cache;
cacheR->zone = zone;
splineKeyPtr->cacheHand = (sb_CacheHeadHdl) cache;
splineKeyPtr->cacheZone = zone;
splineKeyPtr->cachePlace = cachePlace;
HNoPurge( cache );
} else {
if (cache = sb_SizeTheBlock( splineKey, cacheR->cache, &zone, sb_FigureCacheSize(widthTabHand),
kKeepContents, cachePlace, doShrink )) {
if (!(result = sb_SetNewSFNT(widthTabHand))) {
if (!(result = sb_InitCacheHead(widthTabHand, (sb_CacheHeadHdl)cache))) {
cacheR = *splineKeyPtr->cacheListHandle + cachePlace; /* <34> */
cacheR->cache = cache; /* <34> */
cacheR->zone = zone; /* <34> */
splineKeyPtr->cacheHand = (sb_CacheHeadHdl)cacheR->cache; /* <34> */
splineKeyPtr->cacheZone = cacheR->zone; /* <34> */
splineKeyPtr->cachePlace = cachePlace; /* <34> */
HNoPurge(cache);
}
}
if (result) { /* <34> */
cacheR = *splineKeyPtr->cacheListHandle + cachePlace; /* <34> */
cacheR->cache = 0;
cacheR->zone = 0;
DisposHandle(cache); /* Get rid of cachehandle */
sb_Debug();
}
} else result = GROWZONE_HANDLE_ERR;
}
} /* End If */
return result;
} /* End sb_LoadNewCache */
/*********************************************************************************************
** sb_SearchForCache
**
** Find the cache that matches the width table request…
** • Check if the current one is okay - FAST CASE
** • NOT FOUND: Check through the list of caches to see if one exists
** • NOT FOUND: Get a brand new one
** • NOT FOUND: re-use a cache
**
*/
pascal long sb_SearchForCache( widthTableHdl widthTabHand )
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND; /* <28-CEL> */
register sb_SplineKeyPtr splineKeyPtr = *splineKey; /* <28-CEL> */
register widthTablePtr widTabPtr = *widthTabHand; /* <27-CEL> */
long result = NO_ERR;
char* hiliteModePtr = HILITEMODE;
register Boolean squashed = !(*hiliteModePtr & PRESERVE_GLYPH);
short splineKeyState, fontState, workHandState;
register Handle aCacheHand = splineKeyPtr->cacheHand;
if (aCacheHand && *aCacheHand) { /* Current cache okay??? Fast case */
sb_CacheHeadPtr cachePtr = (sb_CacheHeadPtr)*aCacheHand;
if ( sb_CacheSFNTMatch(cachePtr, widTabPtr) && cachePtr->squashed == squashed)
return NO_ERR;
else HPurge((Handle)aCacheHand); /* <16-CEL> */
}
splineKeyPtr->cacheHand = 0; /* we need a new current cache */
splineKeyPtr->cacheZone = 0; /* <16-CEL> */
splineKeyPtr->cachePlace = 0; /* <16-CEL> */
widTabPtr = *widthTabHand;
splineKeyPtr = *splineKey;
splineKeyState = HGetState ((Handle)splineKey);
fontState = HGetState ((Handle)widTabPtr->tabFont);
HLock((Handle)splineKey); /* <32-CEL> */
HNoPurge(widTabPtr->tabFont);
if (!(result = sb_CheckWorkHandle())) { /* <32-CEL> */
workHandState = HGetState ((Handle)splineKeyPtr->fsWorkHand);
HNoPurge(splineKeyPtr->fsWorkHand); /* <32-CEL> */
if (splineKeyPtr->cacheListHandle || !(result = sb_ModCacheList(splineKey)))
result = sb_LoadNewCache(splineKey, widthTabHand, squashed);
HSetState((Handle)splineKeyPtr->fsWorkHand, workHandState);
}
HPurge((Handle)(*splineKey)->cacheHand); /* 15-CEL */
HSetState((Handle)splineKey, splineKeyState);
HSetState((*widthTabHand)->tabFont, fontState);
return result;
} /* End sb_SearchForCache */
/***************************************************************************************************/
/***************************************************************************************************/
/**********************************/
/* ROUTINES THAT CALL FONT SCALER */
/**********************************/
/*********************************************************************************************
** sb_SetUpWorkHand
**
** sb_SetUpWorkHand
**
**
*/
static long sb_SetUpWorkHand()
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
long position = 0;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
short splineKeyState = HGetState ((Handle)splineKey);
long result;
register char *memoryPtr;
HLock((Handle)splineKey);
splineKeyPtr->inputOffset = position;
position += LONG_WORD_ALIGN(sizeof(fs_GlyphInputType));
splineKeyPtr->infoOffset = position;
position += LONG_WORD_ALIGN( sizeof(fs_GlyphInfoType));
if (result = sb_SizeWorkHandle(position, kNoOptions, noShrink)) goto EXIT; /* Error so can not continue */
memoryPtr = *splineKeyPtr->fsWorkHand;
splineKeyPtr->inPtr = (fs_GlyphInputType *)(memoryPtr + splineKeyPtr->inputOffset);
splineKeyPtr->outPtr = (fs_GlyphInfoType *)(memoryPtr + splineKeyPtr->infoOffset);
(*splineKeyPtr->inPtr).GetSfntFragmentPtr = (GetSFNTFunc)QDGetFontFrag;
(*splineKeyPtr->inPtr).ReleaseSfntFrag = (ReleaseSFNTFunc)QDUngetFontFrag;;
/* reinitialize the state to make sure the FS gets ran through */
sb_ResetFSWorkState(splineKeyPtr);
if (!(result = fs_OpenFonts( splineKeyPtr->inPtr, splineKeyPtr->outPtr ))) {
/*******************/
/* SETTING OFFSETS */
/*******************/
splineKeyPtr->globalOffset0 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[0]);
splineKeyPtr->globalOffset1 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[1]);
splineKeyPtr->globalOffset2 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[2]);
splineKeyPtr->sfntDataOffset3 = position;
/*******************/
/***********************/
/** FSWorkHand HANDLE **/
/***********************/
if (!(result = sb_SizeWorkHandle( position, kKeepContents, noShrink ))) {
sb_SetMemPtrs(0);
if (result = fs_Initialize( splineKeyPtr->inPtr, splineKeyPtr->outPtr ))
sb_Debug();
}
} /* End if */
EXIT:
HSetState((Handle)splineKey, splineKeyState);
return result;
} /* End sb_SetUpWorkHand */
/*********************************************************************************************
** sb_SFNTMatchSize
**
** sb_SFNTMatchSize
**
**
*/
pascal Boolean sb_SFNTMatchSize(Handle /*sfntHand*/, short /*matchSize*/)
{
return true;
} /* End sb_SFNTMatchSize */
/*********************************************************************************************
** AppendSplineDirectoryToWidthTable
**
** AppendSplineDirectoryToWidthTable
**
** This routine appends the spline directory for the sfnt specified by the widthTableHandle's
** tabFont field to the end of the widthTableHandle by resizing the widthTableHandle and
** blockmoving the directory data.
**
*/
long AppendSplineDirectoryToWidthTable( Handle splineHandle, widthTableHdl widthTableHandle )
{
// Locals
long error;
Size splineDirectorySize;
sfnt_OffsetTable* splineDirectoryPointer;
error = memFullErr;
splineDirectoryPointer = (sfnt_OffsetTable*) QDGetFontFrag( splineHandle, 0, OFFSETTABLESIZE );
if ( splineDirectoryPointer != nil ) {
splineDirectorySize = OFFSETTABLESIZE + (splineDirectoryPointer->numOffsets * sizeof(sfnt_DirectoryEntry));
QDUngetFontFrag( splineHandle, splineDirectoryPointer );
splineDirectoryPointer = (sfnt_OffsetTable*) QDGetFontFrag( splineHandle, 0, splineDirectorySize );
if ( splineDirectoryPointer != nil ) {
SetHandleSize( (Handle) widthTableHandle, sizeof( widthTable ) + splineDirectorySize );
if ( (error = MemError( )) == noErr ) {
BlockMove( (Ptr) splineDirectoryPointer, (Ptr) (*widthTableHandle)->fSplineDirectory, splineDirectorySize );
}
}
QDUngetFontFrag( splineHandle, splineDirectoryPointer );
}
return( error );
}
/*********************************************************************************************
** sb_FillWidthTab
**
** sb_FillWidthTab
**
** This routine is called by the Font Manager when a new font width table needs to be filled
** out with the proper metrics for spline fonts.
**
*/
pascal long sb_FillWidthTab(widthTableHdl widthTabHand, Boolean fractEnable)
{
register sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register widthTablePtr widTabPtr = *widthTabHand;
short FontHandState = HGetState (widTabPtr->tabFont);
FMOutput *fmRecPtr = &FMOUTPUT_PTR;
register long result = NO_ERR;
Boolean runInMinMode = false;
#ifndef SYSTEM_7
if (!splineKeyPtr->mfExists) /* If it's not already running, check */
splineKeyPtr->mfExists = MultiFinderExist();
#endif
HNoPurge(widTabPtr->tabFont);
widTabPtr->vOutput = 1 << 8; /* reset to no factor */
widTabPtr->hOutput = 1 << 8;
widTabPtr->vFactor = 1 << 8;
widTabPtr->hFactor = 1 << 8;
widTabPtr->notFast = (fmRecPtr->boldPixels || fmRecPtr->ulThick || fmRecPtr->shadowPixels);
widTabPtr->trans00 = FixDiv(widTabPtr->inNumer.h, widTabPtr->inDenom.h);
widTabPtr->trans11 = FixDiv(widTabPtr->inNumer.v, widTabPtr->inDenom.v);
if (widTabPtr->aFace & OBLIQUE_BIT) {
if (widTabPtr->aSize <= 8) {
widTabPtr->trans10 = (widTabPtr->trans00) / 2;
} else if (widTabPtr->aSize <= 16) {
widTabPtr->trans10 = (widTabPtr->trans00) / 3;
} else if (widTabPtr->aSize <= 22) {
widTabPtr->trans10 = (widTabPtr->trans00) / 4;
} else {
widTabPtr->trans10 = (widTabPtr->trans00) / 5;
}
} else widTabPtr->trans10 = 0L;
result = AppendSplineDirectoryToWidthTable( widTabPtr->tabFont, widthTabHand );
if ( result == noErr ) {
widTabPtr = *widthTabHand;
if ((result = sb_CheckWorkHandle()) == MEM_ERR) {
splineKeyPtr = *splineKey;
if (!(result = sb_ShrinkCacheToMin(splineKeyPtr->cacheHand, 0))) {
runInMinMode = true;
result = sb_CheckWorkHandle();
}
}
if (!result) {
splineKeyPtr = *splineKey;
HNoPurge(splineKeyPtr->fsWorkHand); /* <30-CEL> */
if (((result = sb_SetNewSFNT(widthTabHand)) == MEM_ERR) && !runInMinMode) {
splineKeyPtr = *splineKey;
if (!(result = sb_ShrinkCacheToMin(splineKeyPtr->cacheHand, 0)))
result = sb_SetNewSFNT(widthTabHand);
}
splineKeyPtr = *splineKey;
if (!result) {
widTabPtr = *widthTabHand;
sb_SetMemPtrs(widthTabHand);
result = fs_FillWidthTable(splineKeyPtr->inPtr, (Fixed*)widTabPtr, widTabPtr->tabFont, widTabPtr->style, widTabPtr->fID, !fractEnable);
if (result)
sb_Debug();
}
HPurge(splineKeyPtr->fsWorkHand); /* <30-CEL> */
}
}
HSetState((**widthTabHand).tabFont, FontHandState);
return (**widthTabHand).badFontFlag = result;
} /* End sb_FillWidthTab */
/*********************************************************************************************
** sb_FillPrinterWidths
**
** sb_FillPrinterWidths
**
** This routine is called by the Font Manager when a new font width table needs to be filled
** out with the proper metrics for spline fonts.
**
*/
pascal long sb_FillPrinterWidths(Fixed *widthsArrayPtr, Handle sfntHand)
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND; /*<16> removed register */
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register long result = NO_ERR;
register widthTablePtr widTabPtr;
#ifndef SYSTEM_7
if (!splineKeyPtr->mfExists) /* If it's not already running, check */
splineKeyPtr->mfExists = MultiFinderExist();
#endif
HLock( (Handle)splineKey );
if (result = sb_CheckWorkHandle()) goto CLEANUP;
HNoPurge(splineKeyPtr->fsWorkHand); /* <28-CEL> */
if (!splineKeyPtr->tempWidthTabHand) {
splineKeyPtr->tempWidthTabHand = (widthTableHdl)NewHandleSys(sizeof(widthTable));
result = MemError();
} else if (!*splineKeyPtr->tempWidthTabHand) {
THz prevZone = GetZone();
SetZone(SystemZone());
ReallocHandle((Handle)splineKeyPtr->tempWidthTabHand, sizeof(widthTable));
result = MemError();
SetZone(prevZone);
}
if (!result) {
widTabPtr = *splineKeyPtr->tempWidthTabHand;
widTabPtr->tabFont = sfntHand;
widTabPtr->fSize = 1;
widTabPtr->inNumer.h = 1;
widTabPtr->inNumer.v = 1;
widTabPtr->inDenom.h = 1;
widTabPtr->inDenom.v = 1;
widTabPtr->face = 0;
widTabPtr->aFace = 0;
widTabPtr->aSize = 1;
widTabPtr->trans00 = 1L << 16;
widTabPtr->trans11 = 1L << 16;
widTabPtr->trans10 = 0;
result = AppendSplineDirectoryToWidthTable( sfntHand, splineKeyPtr->tempWidthTabHand );
if ( result == noErr ) {
if (result = sb_SetNewSFNT ( splineKeyPtr->tempWidthTabHand ))
sb_Debug();
else {
short sfntID; /* hack, should be id of this sfnt (passed in by caller) */
ResType sfntType;
Str255 sfntName;
GetResInfo( sfntHand, &sfntID, &sfntType, &sfntName[0] );
sb_SetMemPtrs(splineKeyPtr->tempWidthTabHand);
if (result = fs_FillWidthTable(splineKeyPtr->inPtr, widthsArrayPtr, sfntHand, 0, sfntID, 0))
sb_Debug();
}
}
} else sb_Debug();
HPurge(splineKeyPtr->fsWorkHand); /* <28-CEL> */
CLEANUP:
HPurge((Handle)(splineKeyPtr->tempWidthTabHand)); /* Do not need if memory is needed */
HUnlock((Handle)splineKey);
return result;
} /* End sb_FillPrinterWidths */
/*********************************************************************************************
** sb_PreFlightFontMem
**
** sb_PreFlightFontMem
**
** LONG_WORD_ALIGN((ppem+8) >> 3) == scan bytes long aligned.
**
** Called by: DrText, FMSwapFont
**
** This preflighting will get better!!!
*/
#define CACHE_ARRAY_SIZE 1024
pascal long sb_PreFlightFontMem ( widthTableHdl widTabHand, Handle fontHandle, short scanLines, short ppem )
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register long result = NO_ERR;
Handle tempHand;
register long bitAndSlopSpace;
register widthTablePtr widTabPtr = *widTabHand;
short fontHandState;
#ifndef SYSTEM_7
if (!splineKeyPtr->mfExists) /* If it's not already running, check */
splineKeyPtr->mfExists = MultiFinderExist();
#endif
fontHandState = HGetState(fontHandle);
HNoPurge(fontHandle);
result = AppendSplineDirectoryToWidthTable( fontHandle, widTabHand );
if ( result == noErr ) {
if (!(result = sb_CheckWorkHandle())) {
splineKeyPtr = *splineKey;
sb_ResetFSWorkState(splineKeyPtr);
HNoPurge(splineKeyPtr->fsWorkHand);
sb_SetMemPtrs(widTabHand);
(*splineKeyPtr->inPtr).clientID = fontHandle;
if (!(result = sb_SetFontMemory(splineKey, widTabHand))) {
register short calcRowBytes = (LONG_WORD_ALIGN((ppem+8) >> 3));
scanLines = 4; /* Hard code minumum band */
bitAndSlopSpace = scanLines * calcRowBytes;
bitAndSlopSpace += (sizeof(sb_CacheHead) + CACHE_ARRAY_SIZE);
/* bitAndSlopSpace += (ppem * calcRowBytes); */ /* for scan converter extra */
if (!(tempHand = sb_GetBitMapSpace(bitAndSlopSpace))) {
result = PRE_FLIGHT_ERR;
} else HPurge(tempHand);
}
HPurge((*splineKey)->fsWorkHand);
}
}
HSetState(fontHandle, fontHandState);
return result;
} /* End sb_PreFlightFontMem */
/*********************************************************************************************
** sb_RenderGlyphInfo
**
** sb_RenderGlyphInfo
**
*/
static long sb_RenderGlyphInfo ( sb_SplineKeyHdl splineKey, widthTableHdl widTabHand, long addEntryOffset )
{
register sb_SplineKeyPtr splineKeyPtr;
register widthTablePtr widTabPtr;
register sb_CacheHeadPtr cachePtr;
register fs_GlyphInfoType *infoPtr;
register sb_GlyphData *glyphDataPtr;
char *hiliteModePtr = HILITEMODE;
long result;
BitMap *bitMapPtr;
int16 ascent, descent, yMax, yMin;
Fixed newTrans11 = (*widTabHand)->trans11;
unsigned char resetTrans = 0; /* <14> */
SQUASH:
if (result = sb_SetNewSFNT ( widTabHand )) return result;
/* re-estab ptrs */
splineKeyPtr = *splineKey;
widTabPtr = *widTabHand;
cachePtr = *splineKeyPtr->cacheHand;
glyphDataPtr = (sb_GlyphData *)((char *)cachePtr + addEntryOffset);
sb_SetMemPtrs(widTabHand);
#if TheFuture /* <18 > EBITMAP */
(*splineKeyPtr->inPtr).param.newglyph.bitmapMethodPreferences = 1;
(*splineKeyPtr->inPtr).param.newglyph.scalingPreference = 0;
#endif
(*splineKeyPtr->inPtr).param.newglyph.characterCode = glyphDataPtr->glyphID;
if (result = fs_NewGlyph( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
sb_Debug();
return result;
}
(*splineKeyPtr->inPtr).param.gridfit.styleFunc = 0;
(*splineKeyPtr->inPtr).param.gridfit.traceFunc = 0;
#if TheFuture /* <18 > EBITMAP */
if (result = fs_GetGlyphInfo( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
sb_Debug();
return result;
}
if (!(*splineKeyPtr->outPtr).outlinesExist) {
return SKIP_CHAR; /* really means char is ok, but has no contours */
}
#endif
#if !TheFuture /* <18 > EBITMAP */
if (result = fs_ContourGridFit( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
sb_Debug();
return result;
}
if (!(*splineKeyPtr->outPtr).outlinesExist) {
return SKIP_CHAR; /* really means char is ok, but has no contours */
}
if (result = fs_FindBitMapSize( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
sb_Debug();
return result;
}
#endif
ascent = (cachePtr->ascent >> 16);
descent = -(cachePtr->descent >> 16); /* turn back into its true sign */
infoPtr = (fs_GlyphInfoType *)splineKeyPtr->outPtr;
bitMapPtr = &(infoPtr->bitMapInfo);
glyphDataPtr->yMin = yMin = bitMapPtr->bounds.top;
glyphDataPtr->yMax = yMax = bitMapPtr->bounds.bottom;
/* Squashing */
if ( !(*hiliteModePtr & PRESERVE_GLYPH) && (resetTrans<2) && (yMax > ascent || yMin < descent)) /* <14> */
{
Fixed maxTrans11, minTrans11; /* <14> */
++resetTrans; /* <14> */
if (yMax > ascent && ascent > 0) /* <14> */
maxTrans11 = ShortMulDiv(widTabPtr->trans11, ascent, yMax); /* <14> */
else maxTrans11 = widTabPtr->trans11; /* <14> */
if (yMin < descent && descent < 0) /* <14> */
minTrans11 = ShortMulDiv(widTabPtr->trans11, descent, yMin); /* <14> */
else minTrans11 = widTabPtr->trans11; /* <14> */
widTabPtr->trans11 = (maxTrans11 < minTrans11) ? maxTrans11 : minTrans11;/* <14> */
goto SQUASH;
} /* End Testing no line height */
glyphDataPtr->lsb = infoPtr->metricInfo.leftSideBearing.x;
glyphDataPtr->devLSB = infoPtr->metricInfo.devLeftSideBearing.x >> 16;
glyphDataPtr->xMin = infoPtr->bitMapInfo.bounds.left;
glyphDataPtr->bitWidth = bitMapPtr->bounds.right - bitMapPtr->bounds.left;
glyphDataPtr->scan = yMax - yMin;
glyphDataPtr->byteWidth = glyphDataPtr->scanByteWidth = (uint32)bitMapPtr->rowBytes;
widTabPtr->trans11 = newTrans11; /* <14> */
return NO_ERR;
} /* End sb_RenderGlyphInfo */
/*********************************************************************************************
** sb_RenderMemShrink
**
**
**
*/
long sb_RenderMemShrink(sb_SplineKeyHdl splineKey, long *addEntryOffset, Boolean *runInMinMode)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register sb_CacheHeadPtr cachePtr;
long result;
if (result = sb_ShrinkCacheToMin(splineKeyPtr->cacheHand, *addEntryOffset)) {
sb_Debug();
return result;
} else {
*runInMinMode = true;
cachePtr = *splineKeyPtr->cacheHand;
*addEntryOffset = cachePtr->addEntryOffset;
}
return NO_ERR;
} /* End sb_RenderMemShrink */
/*********************************************************************************************
** sb_RoomForHead
** Make room for the header
**
** MOVES MEMORY
**
*/
long sb_RoomForHead(sb_SplineKeyHdl splineKey, long *addEntryOffset, Boolean *runInMinMode)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
long cacheSize;
register Handle tempHand;
/**************************
** Make room for the header
**
** MOVES MEMORY
*/
cacheSize = GetHandleSize((Handle)splineKeyPtr->cacheHand);
if (GLYPH_HEAD_BYTES > ( cacheSize - *addEntryOffset )) {
THz zone = splineKeyPtr->cacheZone;
if (tempHand = sb_SizeTheBlock(splineKey, (Handle)splineKeyPtr->cacheHand, &zone,
*addEntryOffset + GLYPH_HEAD_BYTES, kKeepContents,
splineKeyPtr->cachePlace, noShrink)) {
splineKeyPtr = *splineKey;
splineKeyPtr->cacheHand = (sb_CacheHeadHdl)tempHand;
splineKeyPtr->cacheZone = zone;
} else return(sb_RenderMemShrink(splineKey, addEntryOffset, runInMinMode));
}
return NO_ERR;
} /* End sb_RoomForHead */
/*********************************************************************************************
** sb_RangeCheck
**
**
**
*/
long sb_RangeCheck(sb_CacheHeadPtr cachePtr, sb_GlyphData *glyphDataPtr,
short yMin16, short yMax16, long addEntryOffset, long glyphEntryOffset)
{
/****** Font Scaler may return completely bogus values because of a bad font *******/
/***** is the font bad???? do some range checking ******/
if (!glyphDataPtr->scan ||
glyphDataPtr->yMax < yMin16 ||
glyphDataPtr->yMin > yMax16 ||
glyphDataPtr->bitWidth == 0 ||
glyphDataPtr->bitWidth > ((short)(cachePtr->widMax >> 16) * 2) ||
(glyphDataPtr->yMax - glyphDataPtr->yMin) > ((yMax16 << 1) - yMin16)) {
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) = (addEntryOffset | ERROR_ENTRY_BIT);
sb_Debug( );
return ENTRY_ERROR;
}
return NO_ERR;
} /* End sb_RangeCheck */
/*********************************************************************************************
** sb_SquishFailAdjust
**
** Squish Failure Adjustment
**
** If squishing was not enough, then clip away to
** keep in range
**
**
**
*/
sb_SquishFailAdjust(sb_GlyphData *glyphDataPtr, sb_Glyph *glyphPtr,
short yMin16, short yMax16, Boolean *doBits, Boolean bitsCached)
{
if (glyphDataPtr->yMax > yMax16) glyphDataPtr->yMax = yMax16;
if (glyphDataPtr->yMin < yMin16) glyphDataPtr->yMin = yMin16;
glyphDataPtr->scan = glyphDataPtr->yMax - glyphDataPtr->yMin;
glyphDataPtr->adjustTop = yMax16 - glyphDataPtr->yMax;
glyphPtr->yMin = glyphDataPtr->yMin;
glyphPtr->yMax = glyphDataPtr->yMax;
glyphPtr->scan = glyphDataPtr->scan;
if (!bitsCached || glyphPtr->clipVert) {
if (glyphPtr->topClip < glyphDataPtr->yMax) glyphPtr->yMax = glyphPtr->topClip;
if (glyphPtr->botClip > glyphDataPtr->yMin) glyphPtr->yMin = glyphPtr->botClip;
glyphPtr->scan = glyphPtr->yMax - glyphPtr->yMin;
if (glyphPtr->scan <= 0) *doBits = false;
}
return;
} /* End sb_SquishFailAdjust */
/*********************************************************************************************
** sb_GrowForGlyphData
**
**
**
*/
long sb_GrowForGlyphData(sb_SplineKeyHdl splineKey, widthTableHdl widTabHand, sb_GlyphData *glyphDataPtr,
long *addEntryOffset, Boolean *runInMinMode, Boolean bitsCached,
long *dataByteSize)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
widthTablePtr widTabPtr = *widTabHand;
register Handle tempHand;
long result;
long cacheSize;
/***********************
** CALC THE DATA SIZE
*/
if (bitsCached) {
*dataByteSize = ((glyphDataPtr->scanByteWidth * glyphDataPtr->scan) + 3) & ~3;
} else {
sb_SetMemPtrs(widTabHand);
fs_SizeOfOutlines( splineKeyPtr->inPtr, splineKeyPtr->outPtr );
*dataByteSize = ((*splineKeyPtr->outPtr).outlineCacheSize + 3) & ~3;
}
/************************************
** Check CACHE size - MOVES MEMORY
*/
cacheSize = GetHandleSize((Handle)splineKeyPtr->cacheHand);
if (*dataByteSize + GLYPH_HEAD_BYTES > cacheSize - *addEntryOffset) {
THz zone = splineKeyPtr->cacheZone;
if (!(tempHand = sb_SizeTheBlock( splineKey, (Handle)splineKeyPtr->cacheHand, &zone,
*addEntryOffset + *dataByteSize + GLYPH_HEAD_BYTES + INCREASE_CACHE,
kKeepContents, splineKeyPtr->cachePlace, noShrink))) {
splineKeyPtr = *splineKey; /* Try for minimum chunk */
tempHand = sb_SizeTheBlock( splineKey, (Handle)splineKeyPtr->cacheHand, &zone,
*addEntryOffset + GLYPH_HEAD_BYTES + *dataByteSize,
kKeepContents, splineKeyPtr->cachePlace, noShrink);
}
if (tempHand) {
splineKeyPtr = *splineKey;
splineKeyPtr->cacheHand = (sb_CacheHeadHdl)tempHand;
splineKeyPtr->cacheZone = zone;
} else if (!*runInMinMode) {
if (result = sb_RenderMemShrink(splineKey, addEntryOffset, runInMinMode))
return result;
} else return GROWZONE_HANDLE_ERR;
}
return NO_ERR;
} /* End sb_GrowForGlyphData */
/*********************************************************************************************
** sb_GrowWork6and7
**
**
**
*/
long sb_GrowWork6and7(sb_SplineKeyHdl splineKey, widthTableHdl widTabHand,
long *addEntryOffset, Boolean *runInMinMode)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
widthTablePtr widTabPtr = *widTabHand;
long result, position;
/*********************************************
** Do the clipping dance - CAN MOVE MEMORY
**
** <6> new memory for the scan converter
*/
sb_SetMemPtrs(widTabHand);
position = splineKeyPtr->rowArrayOffset6 + LONG_WORD_ALIGN(splineKeyPtr->outPtr->memorySizes[6]);
if (!*runInMinMode) {
splineKeyPtr->columnArrayOffset7 = position;
position += LONG_WORD_ALIGN(splineKeyPtr->outPtr->memorySizes[7]);
}
if ((result = sb_SizeWorkHandle( position, kKeepContents, doShrink )) && !*runInMinMode)
if (!(result = sb_RenderMemShrink(splineKey, addEntryOffset, runInMinMode)))
result = sb_SizeWorkHandle( position, kKeepContents, doShrink );
return result;
} /* End sb_GrowWork6and7 */
/*********************************************************************************************
** sb_GetMemForBits
**
**
**
*/
long sb_GetMemForBits(sb_SplineKeyHdl splineKey, widthTableHdl widTabHand,
sb_Glyph *glyphPtr, Boolean *runInMinMode, long *addEntryOffset,
short yMax16, long memForScanLine)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register widthTablePtr widTabPtr = *widTabHand;
register sb_CacheHeadPtr cachePtr = *splineKeyPtr->cacheHand;
register sb_GlyphData *glyphDataPtr = (char *)cachePtr + *addEntryOffset;
short scanBytes = glyphDataPtr->scanByteWidth;
Handle tempHand;
long bmSize;
long result, position;
Boolean bandGlyph = false;
if (glyphPtr->nextBand) {
glyphDataPtr->yMax = glyphPtr->yMax = glyphPtr->nextTopBand;
if (glyphPtr->nextTopBand - glyphPtr->nextBotBand <= glyphPtr->bandScan) {
glyphDataPtr->yMin = glyphPtr->yMin = glyphPtr->nextBotBand;
} else {
glyphDataPtr->yMin = glyphPtr->yMin = glyphPtr->yMax - glyphPtr->scan;
glyphPtr->nextTopBand = glyphPtr->yMin;
}
glyphDataPtr->scan = glyphPtr->scan = glyphPtr->yMax - glyphPtr->yMin;
glyphDataPtr->adjustTop = yMax16 - glyphDataPtr->yMax;
}
bmSize = glyphPtr->scan * scanBytes;
if (*runInMinMode && !glyphPtr->nextBand) {
sb_SetMemPtrs(widTabHand);
position = splineKeyPtr->rowArrayOffset6 + LONG_WORD_ALIGN(memForScanLine*glyphPtr->scan);
if (result = sb_SizeWorkHandle( position, kKeepContents, doShrink ))
bandGlyph = true;
}
tempHand = nil; /* init to nil */
if (!bandGlyph || glyphPtr->nextBand) {
if (!(tempHand = sb_GetBitMapSpace(bmSize))) {
if (!glyphPtr->nextBand) {
if (!*runInMinMode) {
if (result = sb_RenderMemShrink(splineKey, addEntryOffset, runInMinMode))
return result;
}
bandGlyph = true;
} else {
glyphPtr->nextBand = false; /* second time so we are in trouble */
sb_Debug();
return MEM_ERR;
}
} else if (glyphPtr->yMin == glyphPtr->nextBotBand)
glyphPtr->nextBand = false; /* finished char loop */
}
if (bandGlyph) { /* could still not get the bitmap */
if (tempHand = sb_BandChar(splineKey, &glyphPtr->scan, scanBytes, memForScanLine)) {
splineKeyPtr = *splineKey;
cachePtr = (sb_CacheHead *)*splineKeyPtr->cacheHand;
glyphDataPtr = (sb_GlyphData *)((char *)cachePtr + *addEntryOffset);
glyphPtr->nextBand = true;
glyphPtr->nextBotBand = glyphPtr->yMin;
glyphDataPtr->yMin = glyphPtr->yMin = glyphPtr->yMax - glyphPtr->scan;
glyphPtr->nextTopBand = glyphPtr->yMin;
glyphDataPtr->scan = glyphPtr->bandScan = glyphPtr->scan;
glyphDataPtr->yMax = glyphPtr->yMax;
} else {
sb_Debug();
return MEM_ERR;
}
}
/* This is a temporary hack!!! This fixes the problem with low memory banding */
if (glyphPtr->topClip - glyphPtr->botClip == 0 && glyphPtr->nextBand)
glyphPtr->nextBand = false;
glyphPtr->bitMapPtr = (uint32 *)*tempHand;
HPurge(tempHand);
return NO_ERR;
} /* End sb_GetMemForBits */
/*********************************************************************************************
** sb_DoTheBits
**
**
**
*/
long sb_DoTheBits(sb_SplineKeyHdl splineKey, widthTableHdl widTabHand, register sb_Glyph *glyphPtr,
short topClip, short bottomClip, Boolean bitsCached, Boolean runInMinMode,
long addEntryOffset, long glyphEntryOffset)
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register widthTablePtr widTabPtr = *widTabHand;
register sb_CacheHeadPtr cachePtr = *splineKeyPtr->cacheHand;
register sb_GlyphData *glyphDataPtr = (char *)cachePtr + addEntryOffset;
long result;
sb_SetMemPtrs(widTabHand);
(*splineKeyPtr->inPtr).memoryBases[5] = (char *)glyphPtr->bitMapPtr; /* bitmap space */
(*splineKeyPtr->inPtr).param.scan.topClip = topClip;
(*splineKeyPtr->inPtr).param.scan.bottomClip = bottomClip;
if (runInMinMode) (*splineKeyPtr->inPtr).memoryBases[7] = 0;
#if TheFuture /* <18 > EBITMAP */
if (result = fs_GetGlyphData( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) |= ERROR_ENTRY_BIT;
sb_Debug();
return result;
}
#endif
#if !TheFuture /* <18 > EBITMAP */
if (result = fs_ContourScan( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) |= ERROR_ENTRY_BIT;
sb_Debug();
return result;
}
#endif
if ((bitsCached && !runInMinMode) || !glyphPtr->clipVert) { /* <3-CEL> */
sb_ShrinkBitmap( glyphDataPtr, (long *)glyphPtr->bitMapPtr, topClip-bottomClip);
}
glyphPtr->byteWidth = glyphDataPtr->byteWidth;
if (bitsCached && !runInMinMode) { /* <3-CEL> */
int16 sourceYMaxAdjust = glyphDataPtr->yMax - glyphPtr->topClip;
cachePtr->addEntryOffset += (((glyphDataPtr->byteWidth * glyphDataPtr->scan) + 3) & ~3);
if (sourceYMaxAdjust > 0)
glyphPtr->bitMapPtr = (uint32 *)((char *)glyphPtr->bitMapPtr + (sourceYMaxAdjust * glyphDataPtr->byteWidth));
}
return NO_ERR;
} /* End sb_DoTheBits */
/*********************************************************************************************
** sb_RenderGlyph
**
**
**
*/
static long sb_RenderGlyph( sb_SplineKeyHdl splineKey, widthTableHdl widTabHand, register sb_Glyph *glyphPtr )
{
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register widthTablePtr widTabPtr = *widTabHand;
register sb_CacheHeadPtr cachePtr = *splineKeyPtr->cacheHand;
Boolean bitsCached = cachePtr->bitsCached;
long addEntryOffset = cachePtr->addEntryOffset;
register sb_GlyphData *glyphDataPtr = (char *)cachePtr + addEntryOffset;
uint16 yMinAdjust = 0; /* adjust for scan lines out of bounds */
Boolean doBits = true;
short yMax16 = (cachePtr->yMax >> 16);
short yMin16 = (cachePtr->yMin >> 16);
Boolean runInMinMode = false; /* <3-CEL> */
long dataByteSize;
long glyphEntryOffset;
long result;
int16 topClip, bottomClip;
long memForScanLine;
glyphPtr->entryOffset = 0;
if (glyphPtr->nextBand) {
glyphEntryOffset = GetSingleOrDoubleByteGlyphEntryOffset( glyphPtr->glyphID, cachePtr );
runInMinMode = true;
goto DO_NEXT_BAND;
} else if (result = sb_RoomForHead(splineKey, &addEntryOffset, &runInMinMode))
return result;
/************************************
** Re-Establish pointers
*/
splineKeyPtr = *splineKey;
cachePtr = *splineKeyPtr->cacheHand;
glyphDataPtr = (sb_GlyphData *)((char *)cachePtr + addEntryOffset);
glyphDataPtr->glyphID = glyphPtr->glyphID;
if (!runInMinMode) { /* <3-CEL> */
cachePtr->addEntryOffset += GLYPH_HEAD_BYTES; /* For next entry */
}
if ((result = sb_RenderGlyphInfo(splineKey, widTabHand, addEntryOffset)) == MEM_ERR) {
if (!runInMinMode) {
if (result = sb_RenderMemShrink(splineKey, &addEntryOffset, &runInMinMode))
return result;
if (result = sb_RenderGlyphInfo(splineKey, widTabHand, addEntryOffset))
return result;
}
}
/***********************
** Re-establish pointers
*/
splineKeyPtr = *splineKey;
widTabPtr = *widTabHand;
cachePtr = *splineKeyPtr->cacheHand;
glyphDataPtr = (sb_GlyphData *)((char *)cachePtr + addEntryOffset);
/************************************
** Determine glyph position in array
*/
glyphEntryOffset = GetSingleOrDoubleByteGlyphEntryOffset( glyphDataPtr->glyphID, cachePtr );
if (result) {
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) = ERROR_ENTRY_BIT;
return ENTRY_ERROR;
}
if (glyphDataPtr->scan)
memForScanLine = LONG_WORD_ALIGN(splineKeyPtr->outPtr->memorySizes[6])/glyphDataPtr->scan;
if (result = sb_RangeCheck(cachePtr, glyphDataPtr, yMin16, yMax16, addEntryOffset, glyphEntryOffset))
return result;
/**********************************************
** Figure out the bottom and top scan lines
*/
if (!runInMinMode) { /* <3-CEL> */
if (bitsCached)
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) = addEntryOffset;
else
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) = (addEntryOffset | CONTOUR_ENTRY_BIT);
}
sb_SquishFailAdjust(glyphDataPtr, glyphPtr, yMin16, yMax16, &doBits, bitsCached);
if (!glyphDataPtr->scan) { /* <2-CEL> if no scan lines, skip char */
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) = ERROR_ENTRY_BIT;
return ENTRY_ERROR;
}
if (!runInMinMode) {
if (result = sb_GrowForGlyphData(splineKey, widTabHand, glyphDataPtr, &addEntryOffset,
&runInMinMode, bitsCached, &dataByteSize)) {
sb_Debug();
return result;
}
}
if (result = sb_GrowWork6and7(splineKey, widTabHand, &addEntryOffset, &runInMinMode)) {
sb_Debug();
return result;
}
/************************************
** Re-Establish pointers
*/
splineKeyPtr = *splineKey;
widTabPtr = *widTabHand;
cachePtr = (sb_CacheHead *)*splineKeyPtr->cacheHand;
glyphDataPtr = (sb_GlyphData *)((char *)cachePtr + addEntryOffset);
sb_SetMemPtrs(widTabHand);
/************************************
** Make space at tail and init pointers
*/
if (bitsCached) {
glyphPtr->bitMapPtr = (uint32 *)&glyphDataPtr->cacheData[0];
topClip = glyphDataPtr->yMax;
bottomClip = glyphDataPtr->yMin;
} else if (!runInMinMode) {
(*splineKeyPtr->inPtr).param.scan.outlineCache = (long *)&glyphDataPtr->cacheData[0];
if (result = fs_SaveOutlines( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) |= ERROR_ENTRY_BIT;
sb_Debug();
return result;
}
cachePtr->addEntryOffset += dataByteSize;
}
DO_NEXT_BAND:
if (doBits && (runInMinMode || !bitsCached)) { /* <3-CEL> */
if (result = sb_GetMemForBits(splineKey, widTabHand, glyphPtr, &runInMinMode,
&addEntryOffset, yMax16, memForScanLine))
return result;
bottomClip = glyphPtr->yMin;
topClip = glyphPtr->yMax;
}
if (doBits || (bitsCached && !runInMinMode)) {
if (result = sb_DoTheBits(splineKey, widTabHand, glyphPtr, topClip, bottomClip, bitsCached,
runInMinMode, addEntryOffset, glyphEntryOffset)) /* 11-CEL assign result */
return result;
}
glyphPtr->entryOffset = addEntryOffset;
if (!doBits) return NO_BITS;
return NO_ERR;
} /* sb_RenderGlyph */
/*********************************************************************************************
** sb_CheckCache
**
** sb_CheckCache
**
**
*/
pascal long sb_CheckCache( sb_SplineKeyHdl splineKey, widthTableHdl widthTabHand, register sb_Glyph *glyphPtr )
{
register sb_SplineKeyPtr splineKeyPtr;
register widthTablePtr widTabPtr = *widthTabHand;
register sb_CacheHead *cachePtr;
register sb_GlyphData *glyphDataPtr;
long glyphEntryOffset;
register long cacheDataOffset;
Handle tempHand;
long result;
Boolean runInMinMode = false;
if (glyphPtr->nextBand) goto MIN_MODE;
widTabPtr = *widthTabHand;
splineKeyPtr = *splineKey;
cachePtr = *splineKeyPtr->cacheHand;
glyphPtr->entryOffset = 0;
/*********************************************/
/** FIND THE POSITION, OFFSET, AND DATA PTR **/
/*********************************************/
glyphEntryOffset = GetSingleOrDoubleByteGlyphEntryOffset( glyphPtr->glyphID, cachePtr );
cacheDataOffset = (*(uint32*) ((Ptr) cachePtr + glyphEntryOffset)) & ENTRY_MASK;
/********************/
/** FIND THE ENTRY **/
/********************/
if (cacheDataOffset) {
long bmSize;
long position;
glyphDataPtr = (sb_GlyphData *)((char *)cachePtr + cacheDataOffset);
glyphPtr->yMin = glyphDataPtr->yMin;
glyphPtr->yMax = glyphDataPtr->yMax;
glyphPtr->scan = glyphDataPtr->scan;
glyphPtr->byteWidth = glyphDataPtr->scanByteWidth;
if (glyphPtr->clipVert) {
if (glyphPtr->topClip < glyphDataPtr->yMax) glyphPtr->yMax = glyphPtr->topClip;
if (glyphPtr->botClip > glyphDataPtr->yMin) glyphPtr->yMin = glyphPtr->botClip;
glyphPtr->scan = glyphPtr->yMax - glyphPtr->yMin;
if (glyphPtr->scan <= 0) return CLIPPED_OUT;
}
sb_SetMemPtrs(widthTabHand);
(*splineKeyPtr->inPtr).param.scan.outlineCache = (long *)&glyphDataPtr->cacheData[0];
if (result = fs_RestoreOutlines( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
sb_Debug();
return result;
}
/* <6> new memory for the scan converter */
position = splineKeyPtr->rowArrayOffset6 + LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[6]);
splineKeyPtr->columnArrayOffset7 = position;
position += LONG_WORD_ALIGN((*splineKeyPtr->outPtr).memorySizes[7]);
bmSize = glyphPtr->scan * glyphDataPtr->scanByteWidth;
/****************/
/* MOVES MEMORY */
/****************/
if (result = sb_SizeWorkHandle( position, kKeepContents, doShrink )) {
splineKeyPtr = *splineKey;
if (result = sb_ShrinkCacheToMin(splineKeyPtr->cacheHand, cacheDataOffset)) {
sb_Debug();
return result;
} else {
goto MIN_MODE; /* must rerun since data is lost */
}
}
/****************/
/* MOVES MEMORY */
/****************/
if (!(tempHand = sb_GetBitMapSpace(bmSize))) {
splineKeyPtr = *splineKey;
if (result = sb_ShrinkCacheToMin(splineKeyPtr->cacheHand, cacheDataOffset)) {
sb_Debug();
return result;
} else {
goto MIN_MODE; /* must rerun since data is lost */
}
}
HPurge(tempHand);
/****************/
/*************************************************/
/* Re-establish pointers after memory allocation */
splineKeyPtr = *splineKey;
widTabPtr = *widthTabHand;
cachePtr = (sb_CacheHead *)*splineKeyPtr->cacheHand;
glyphDataPtr = (sb_GlyphData *)((char *)cachePtr + cacheDataOffset);
glyphPtr->bitMapPtr = (uint32 *)*tempHand;
sb_SetMemPtrs(widthTabHand);
(*splineKeyPtr->inPtr).memoryBases[5] = (char *)glyphPtr->bitMapPtr;
(*splineKeyPtr->inPtr).param.scan.outlineCache = (long *)&glyphDataPtr->cacheData[0];
(*splineKeyPtr->inPtr).param.scan.bottomClip = glyphPtr->yMin;
(*splineKeyPtr->inPtr).param.scan.topClip = glyphPtr->yMax;
#if TheFuture /* <18 > EBITMAP */
if (result = fs_GetGlyphData( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
sb_Debug();
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) |= ERROR_ENTRY_BIT;
return result;
}
#endif
#if !TheFuture /* <18 > EBITMAP */
if (result = fs_ContourScan( splineKeyPtr->inPtr, splineKeyPtr->outPtr )) {
sb_Debug();
*(uint32*) ((Ptr) cachePtr + glyphEntryOffset) |= ERROR_ENTRY_BIT;
return result;
}
#endif
if (!glyphPtr->clipVert) {
sb_ShrinkBitmap( glyphDataPtr, (long *)glyphPtr->bitMapPtr, glyphPtr->yMax-glyphPtr->yMin);
glyphPtr->byteWidth = glyphDataPtr->byteWidth;
}
glyphPtr->entryOffset = cacheDataOffset;
return NO_ERR;
} /* End If */
MIN_MODE:
return( sb_RenderGlyph(splineKey, widthTabHand, glyphPtr) );
} /* End sb_CheckCache */
/*********************************************************************************************
** sb_RetrieveGlyph
**
** sb_RetrieveGlyph
**
**
*/
pascal long sb_RetrieveGlyph( widthTableHdl widthTabHand, sb_Glyph *glyphPtr )
{
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
register sb_SplineKeyPtr splineKeyPtr = *splineKey;
register widthTablePtr widTabPtr = *widthTabHand;
short fontHandState = HGetState (widTabPtr->tabFont);
short cacheHandState = HGetState ((Handle)splineKeyPtr->cacheHand); /* 15-CEL */
long result;
#ifndef SYSTEM_7
if (!splineKeyPtr->mfExists) /* If it's not already running, check */
splineKeyPtr->mfExists = MultiFinderExist();
#endif
splineKeyPtr->glyphID = glyphPtr->glyphID; /* keep track in key which glyphid */
HNoPurge(widTabPtr->tabFont);
HNoPurge((Handle)splineKeyPtr->cacheHand); /* 15-CEL */
if ((result = sb_CheckWorkHandle()) == MEM_ERR) {
splineKeyPtr = *splineKey;
if (!(result = sb_ShrinkCacheToMin(splineKeyPtr->cacheHand, 0)))
result = sb_CheckWorkHandle();
}
if (!result) {
HNoPurge(splineKeyPtr->fsWorkHand);
/* If banding in TrueType, don't AddGlyphOffset table more than once <KON Sakura2>*/
if (!glyphPtr->nextBand)
result = AddLowByteGlyphOffsetTable( glyphPtr->glyphID, splineKey );
if ( result == noErr ) {
result = sb_CheckCache( splineKey, widthTabHand, glyphPtr );
if ((result == noErr) ||
(result == NO_BITS)) // can be returned by sb_RenderGlyph for some reason
// seems to only happen printing with the StyleWriter
{
CheckForMaximumDiskCacheSize( (*splineKey)->cacheHand );
}
}
HPurge((*splineKey)->fsWorkHand);
}
HSetState((Handle)(*splineKey)->cacheHand, cacheHandState); /* 15-CEL */
HSetState((*widthTabHand)->tabFont, fontHandState);
return result;
} /* End sb_RetrieveGlyph */
/****************************/
/* END CALLS TO FONT SCALER */
/****************************/
/***************************************************************************************************/
/***************************************************************************************************/