mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-10-04 03:57:18 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
975 lines
29 KiB
C
975 lines
29 KiB
C
/*
|
|
File: PartialFontExtensions.c
|
|
|
|
Contains: Partial font extension entry points for the scaler and cache code to
|
|
read and cache outline font data from the disk.
|
|
|
|
Three main structures are necessary for the partial font code:
|
|
|
|
Fragment
|
|
FragmentTable
|
|
FragmentTableCache
|
|
|
|
A fragment is a handle that contains a small header followed by a range
|
|
of data read from an outline font resource. The header identifies where
|
|
the data started in the outline font, it's length, and other attributes.
|
|
|
|
A fragment table is a doubly linked list of fragments for one outline
|
|
font.
|
|
|
|
A fragment table cache is a doubly linked list of fragment tables for
|
|
the entire system.
|
|
|
|
The two most important routines in this file are QDGetFontFrag and
|
|
QDUngetFontFrag. These entry points are used as the GetSfntFragmentPtr
|
|
and ReleaseSfntFrag fields of an input parameter block used to
|
|
communicate with the TrueType scaler.
|
|
|
|
Written by: John Farmer based on work originally written by Mike Reed
|
|
|
|
Copyright: © 1991-1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<SM4> 7/7/92 CSS Roll-in Reality Changes:
|
|
<7> 7/4/92 DTY #1034875 <csd>: Allow InitializePartialFonts to be called more
|
|
than once. On successive calls, if the requested zone size is
|
|
larger than the existing zone size, blow the smaller one away.
|
|
If the requested size is smaller than the existing one, keep the
|
|
existing one.
|
|
<SM3> 6/8/92 CSS Roll-in Reality Changes:
|
|
<6> 4/2/92 DTY #1025909: Commented out calls to VerifyPartialFontStructures and
|
|
the routine itself since it just returns. This will save a few
|
|
bytes of our ever precious memory.
|
|
<5> 4/1/92 YK #1025684: Calculate the number of master pointers initially
|
|
created in the partial font zone, instead of hard-codeing the
|
|
value.
|
|
<4> 4/1/92 YK #1023997: InitializePartialFonts should be a pascal function.
|
|
<3> 3/30/92 DTY #1025684: Make InitializePartialFonts take a Size parameter so
|
|
that the caller can specify how large to make the partial font
|
|
sub-zone.
|
|
<2> 3/27/92 DTY #1024868: Take out calls to assertion routines since they donÕt
|
|
do anything anymore, and the assertion messages are wasting
|
|
memory.
|
|
<SM2> 4/17/92 PN Change InitZone to InitZoneGlue to do ROM build with Bass fonts
|
|
|
|
System 6.1.0 Changes:
|
|
|
|
<3> 08/27/91 John Farmer - Added documentation.
|
|
|
|
<2> 06/03/91 John Farmer - Dispose of at least kMinimumFreeHeapSpace in
|
|
the GrowZone procedure.
|
|
|
|
<1> 03/23/91 John Farmer - Created file and documentation.
|
|
|
|
*/
|
|
|
|
|
|
// Include Statements
|
|
|
|
|
|
#include "BaseIncludes.h"
|
|
#include "Assertion.h"
|
|
#include "Fragment.proto"
|
|
#include "FragmentTable.proto"
|
|
#include "FSCdefs.h"
|
|
#include "MapString.h"
|
|
#include "Memory.h"
|
|
#include "PartialFontExtensions.proto"
|
|
#include "sfnt.h"
|
|
#include "sfnt_enum.h"
|
|
#include "ZoneHandle.proto"
|
|
|
|
#include "FontScaler.h"
|
|
#include "Bass_Cache.h"
|
|
|
|
//¥¥¥¥¥ Temporary hack for INitZone
|
|
extern pascal void INITZONEGLUE (GrowZoneProcPtr pgrowZone,short cmoreMasters,void *limitPtr,
|
|
void *startPtr);
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: partialFontZone = GetPartialFontZone( )
|
|
|
|
Purpose: Return pointer to partial font zone from TrueType globals.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
THz GetPartialFontZone( void )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
|
|
|
|
return( (*splineKey)->fPartialFontZone );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: fragmentTableCache = GetGlobalFontFragmentTableCache( )
|
|
|
|
Purpose: Return handle to fragment table cache.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
FragmentTableCacheStructureHandle GetGlobalFontFragmentTableCache( void )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
|
|
|
|
return( (*splineKey)->fFragmentTableCache );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: VerifyPartialFontStructures
|
|
|
|
Purpose: Inspect partial font data structures for bogus values. Remove the return
|
|
statement at the top of the routine to enable verification.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
#if 0 // <SM3> CSS <6>
|
|
void VerifyPartialFontStructures( void )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
Boolean valid;
|
|
OSErr error;
|
|
Size fragmentSize;
|
|
FragmentStructureHandle fragment;
|
|
FragmentTableStructureHandle fragmentTable;
|
|
FragmentTableCacheStructureHandle fragmentTableCache;
|
|
THz partialFontZone, savedZone;
|
|
|
|
return;
|
|
|
|
error = noErr;
|
|
|
|
partialFontZone = GetPartialFontZone( );
|
|
if ( partialFontZone ) {
|
|
|
|
savedZone = SwapZone( GetPartialFontZone( ) );
|
|
|
|
fragmentTableCache = GetGlobalFontFragmentTableCache( );
|
|
if ( AssertHandle( (Handle) fragmentTableCache ) ) {
|
|
|
|
valid = true;
|
|
fragmentTable = (*fragmentTableCache)->fFirstFragmentTable;
|
|
while ( valid && (fragmentTable != nil) ) {
|
|
|
|
if ( valid = (AssertHandle( (Handle) fragmentTable ) && AssertHandle( (*fragmentTable)->fFontHandle )) ) {
|
|
|
|
fragment = (*fragmentTable)->fFirstFragment;
|
|
while ( valid && (fragment != nil) ) {
|
|
|
|
if ( valid = AssertHandle( (Handle) fragment ) ) {
|
|
|
|
fragmentSize = GetHandleSize( (Handle) fragment );
|
|
if ( valid = ((error = MemError( )) == noErr) ) {
|
|
|
|
if ( valid = (fragmentSize == sizeof( FragmentStructure ) + (*fragment)->fLength) ) {
|
|
|
|
if ( valid = ( (*fragment)->fLockCount >= 0) ) {
|
|
|
|
if ( valid = ( (*fragment)->fOffset >= 0) ) {
|
|
|
|
valid = ( (*fragment)->fLength >= 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fragment = (*fragment)->fNextFragment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fragmentTable = (*fragmentTable)->fNextFragmentTable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SwapZone( savedZone );
|
|
|
|
}
|
|
|
|
}
|
|
#endif // <SM3> CSS <6>
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: PartialFontZoneGrowZoneProcedure( )
|
|
|
|
Purpose: Throw away the least recently used fragments until memoryNeeded bytes is
|
|
obtained. MemoryNeeded is pinned to at least kMinimumFreeHeapSize to limit
|
|
Memory Manager heap compaction and frequent visits to this routine. Only
|
|
unlocked fragments are thrown away.
|
|
|
|
Warnings: If this routine ever fails it means that some very large fragment requests
|
|
are being made by the scaler. The best thing to do is reduce the size of
|
|
the request or increase the size of the partial font heap.
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
pascal Size PartialFontZoneGrowZoneProcedure( Size memoryNeeded )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
OSErr error;
|
|
Size memoryDeallocated, fragmentSize;
|
|
THz savedZone;
|
|
Handle handleFromHell;
|
|
FragmentStructureHandle fragment, previousFragment;
|
|
FragmentTableStructureHandle fragmentTable;
|
|
FragmentTableCacheStructureHandle fragmentTableCache;
|
|
|
|
// VerifyPartialFontStructures( );
|
|
|
|
error = noErr;
|
|
memoryDeallocated = 0;
|
|
fragmentTableCache = GetGlobalFontFragmentTableCache( );
|
|
|
|
handleFromHell = GZSaveHnd( );
|
|
savedZone = SwapZone( GetPartialFontZone( ) );
|
|
|
|
if ( memoryNeeded < kMinimumFreeHeapSpace )
|
|
memoryNeeded = kMinimumFreeHeapSpace;
|
|
|
|
fragmentTable = (*fragmentTableCache)->fLastFragmentTable;
|
|
while ( (fragmentTable != nil) && (memoryDeallocated < memoryNeeded) ) {
|
|
|
|
fragment = (*fragmentTable)->fLastFragment;
|
|
while ( (error == noErr) && (fragment != nil) && (memoryDeallocated < memoryNeeded) ) {
|
|
|
|
previousFragment = (*fragment)->fPreviousFragment;
|
|
if ( ((Handle) fragment != handleFromHell) && ((*fragment)->fLockCount == 0) ) {
|
|
|
|
RemoveFragmentFromFragmentTable( fragment, fragmentTable );
|
|
fragmentSize = GetHandleSize( (Handle) fragment );
|
|
if ( (error = MemError( )) == noErr ) {
|
|
|
|
DisposHandle( (Handle) fragment );
|
|
memoryDeallocated += fragmentSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fragment = previousFragment;
|
|
|
|
}
|
|
|
|
fragmentTable = (*fragmentTable)->fPreviousFragmentTable;
|
|
|
|
}
|
|
|
|
SwapZone( savedZone );
|
|
|
|
// VerifyPartialFontStructures( );
|
|
return( memoryDeallocated );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: InitializePartialFonts( Size partialFontZoneSize )
|
|
|
|
Purpose: Initialize the partial font data structures. Mainly responsible for
|
|
embedding the partial font heap within the system heap, creating an
|
|
empty fragment table cache within the partial font heap, and initializing
|
|
key data structures.
|
|
|
|
Warnings: This routine should be called as earily as possible in the boot process
|
|
to ensure that we do not fragment the system heap.
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
pascal OSErr InitializePartialFonts( Size partialFontZoneSize )
|
|
|
|
{
|
|
|
|
|
|
// Locals
|
|
|
|
OSErr error = noErr;
|
|
THz savedZone;
|
|
sb_SplineKeyHdl splineKey = SPLINE_KEY_HAND;
|
|
Ptr partialFontZone = (Ptr) ((*splineKey)->fPartialFontZone);
|
|
Size existingPartialFontZoneSize;
|
|
FragmentTableCacheStructureHandle fragmentTableCache;
|
|
|
|
// <7> Check to see if a partial font zone already exists. If one does, and itÕs larger
|
|
// than the size that is being requested, return immediately and keep using the old
|
|
// one. If the existing zone is smaller than the requested size, blow it away
|
|
// and create a new one.
|
|
|
|
if ( partialFontZone != nil ) {
|
|
existingPartialFontZoneSize = GetPtrSize(partialFontZone); // <7> Get the size of the existing partial font zone
|
|
if (existingPartialFontZoneSize >= partialFontZoneSize) // <7> Is the existing one larger than the requested one?
|
|
return (noErr); // <7> Yeah. Go ahead and use whatÕs there
|
|
|
|
DisposPtr(partialFontZone); // <7> Otherwise, blow it away.
|
|
(*splineKey)->fPartialFontZone = nil; // <7> Remove the reference to the old zone in case the new one fails to allocate
|
|
(*splineKey)->fFragmentTableCache = nil; // <7> We blew away the fragment table cache too.
|
|
}
|
|
|
|
savedZone = GetZone( );
|
|
|
|
error = NewZonePtr( &partialFontZone, partialFontZoneSize, SystemZone( ) );
|
|
if ( error == noErr ) {
|
|
//¥¥¥¥Temporary hack
|
|
INITZONEGLUE( (GrowZoneProcPtr) PartialFontZoneGrowZoneProcedure, partialFontZoneSize/kPartialFontBytesPerMasterPointer, partialFontZone + partialFontZoneSize, partialFontZone ); //<SM3> <SM4>
|
|
if ( (error = MemError( )) == noErr ) {
|
|
|
|
error = NewZoneHandle( (Handle*) &fragmentTableCache, (Size) sizeof( FragmentTableCacheStructure ), (THz) partialFontZone );
|
|
if ( error == noErr ) {
|
|
|
|
(*fragmentTableCache)->fFirstFragmentTable = nil;
|
|
(*fragmentTableCache)->fLastFragmentTable = nil;
|
|
(*splineKey)->fPartialFontZone = (THz) partialFontZone;
|
|
(*splineKey)->fFragmentTableCache = fragmentTableCache;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetZone( savedZone );
|
|
|
|
|
|
return( error );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: QDGetFontFrag
|
|
|
|
Purpose: Return a pointer to font data starting at 'offset' bytes into a 'sfnt'
|
|
resource. The data is 'length' bytes in size and the data pointer must remain
|
|
valid until a corresponding QDUngetFontFrag call is made.
|
|
|
|
The splineFont is assumed to be loaded into memory if the master pointer of
|
|
the splineFont handle is not nil. In this case, we act like the Roman system
|
|
and add the offset parameter to the splineFont master pointer.
|
|
|
|
If the master pointer is nil, we try to lookup a fragmentTable for the font
|
|
identified by the 'splineFont' parameter. If we find a fragmentTable it
|
|
becomes the current fragmentTable and we attempt to find or create a fragment
|
|
within the fragmentTable.
|
|
|
|
If we do not find a fragmentTable we have to create a new one, add it to
|
|
the fragmentTableCache (which is just a list of fragmentTables in MRU order),
|
|
and call the FindOrCreateFragment routine, which, in this case, simply
|
|
creates the fragment and adds it to the list of fragments in the newly
|
|
created fragmentTable.
|
|
|
|
Once a fragment has been found or created we can return a pointer to the
|
|
data. FindOrCreateFragment is responsible for returning a locked fragment
|
|
handle so we're guaranteed that the data won't move. The returned fragment
|
|
may have a fragment offset less than or equal to the requested fragment
|
|
offset. Therefore, we must offset the data pointer by the different between
|
|
the requested offset and fragment's offset (a picture would be great here).
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
void* QDGetFontFrag( Handle splineFont, long offset, long length )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
OSErr error;
|
|
void* dataPointer;
|
|
Ptr splineMasterPointer;
|
|
FragmentStructureHandle fragment;
|
|
FragmentTableStructureHandle fragmentTable;
|
|
FragmentTableCacheStructureHandle fragmentTableCache;
|
|
|
|
// VerifyPartialFontStructures( );
|
|
|
|
if ( (splineMasterPointer = StripAddress( *splineFont )) != nil ) {
|
|
|
|
dataPointer = splineMasterPointer + offset;
|
|
|
|
} else {
|
|
|
|
error = noErr;
|
|
dataPointer = nil;
|
|
fragment = nil;
|
|
fragmentTableCache = GetGlobalFontFragmentTableCache( );
|
|
|
|
if ( AssertHandle( splineFont ) && AssertHandle((Handle) fragmentTableCache) && (offset >= 0) && (length >= 0) ) {
|
|
|
|
FindFragmentTable( &fragmentTable, splineFont, fragmentTableCache );
|
|
if ( fragmentTable != nil ) {
|
|
|
|
SetCurrentFragmentTable( fragmentTable, fragmentTableCache );
|
|
error = FindOrCreateFragment( &fragment, offset, length, fragmentTable );
|
|
|
|
} else {
|
|
|
|
error = CreateFragmentTable( &fragmentTable, splineFont );
|
|
if ( error == noErr ) {
|
|
|
|
AddFragmentTableToCache( fragmentTable, (*fragmentTableCache)->fFirstFragmentTable, fragmentTableCache );
|
|
error = FindOrCreateFragment( &fragment, offset, length, fragmentTable );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((error == noErr) && (fragment != nil))
|
|
dataPointer = StripAddress( (*fragment)->fData + (offset - (*fragment)->fOffset) );
|
|
|
|
}
|
|
|
|
// VerifyPartialFontStructures( );
|
|
return( dataPointer );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: QDUngetFontFrag
|
|
|
|
Purpose: Unlock a fragment that has been locked through a QDGetFontFrag call.
|
|
After finding the fragmentTable associated with the splineFont parameter
|
|
we have to search through the first few entries of the fragment list
|
|
for the fragmentTable. This is necessary since QDGetFontFrag may return
|
|
a pointer to the middle of a locked handle, which, does no allow us to
|
|
call recover handle. The fragment being released is almost always the
|
|
current fragment in the fragment list since the scaler nests QDGetFontFrag
|
|
and QDUngetFontFrag pairs.
|
|
|
|
The data parameter is the pointer returned by QDGetFontFrag.
|
|
|
|
Warnings: None.
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
void QDUngetFontFrag( Handle splineFont, void* data )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
FragmentStructureHandle fragment;
|
|
FragmentTableStructureHandle fragmentTable;
|
|
FragmentTableCacheStructureHandle fragmentTableCache;
|
|
|
|
// VerifyPartialFontStructures( );
|
|
|
|
if ( (data != nil) && (StripAddress( *splineFont ) == nil) && AssertHandle( splineFont) ) {
|
|
|
|
fragmentTableCache = GetGlobalFontFragmentTableCache( );
|
|
FindFragmentTable( &fragmentTable, splineFont, fragmentTableCache );
|
|
if ( fragmentTable != nil ) {
|
|
|
|
FindFragmentHandle( &fragment, (Ptr) data, fragmentTable );
|
|
if ( fragment != nil ) {
|
|
|
|
UnlockFragment( fragment, fragmentTable );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// VerifyPartialFontStructures( );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: KillApplicationHeapFragmentTableCaches( startAddress, endAddress )
|
|
|
|
Purpose: Search through all fragmentTables in the fragmentTable cache. If a fragmentTable
|
|
is associated with a spline font handle contained within startAddress..endAddress,
|
|
remove the fragmentTable from the fragmentTableCache, remove and dispose of
|
|
each fragment contained within the fragmentTable (ouch), and dispose of the
|
|
fragmentTable.
|
|
|
|
This routine is normally called when an application terminates. If an
|
|
outline font resource has been loaded into the application heap all
|
|
fragments associated with that font will be disposed when the application
|
|
quits. Pacific outline fonts will not have this problem since they are always
|
|
allocated in the system heap as empty handles.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
void KillApplicationHeapFragmentTableCaches( Handle heapStart, Handle heapEnd )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
OSErr error;
|
|
FragmentStructureHandle fragment, nextFragment;
|
|
FragmentTableStructureHandle fragmentTable, nextFragmentTable;
|
|
FragmentTableCacheStructureHandle fragmentTableCache;
|
|
THz partialFontZone;
|
|
|
|
error = noErr;
|
|
|
|
fragmentTableCache = GetGlobalFontFragmentTableCache( );
|
|
if ( fragmentTableCache != nil ) {
|
|
|
|
partialFontZone = GetPartialFontZone( );
|
|
|
|
fragmentTable = (*fragmentTableCache)->fFirstFragmentTable;
|
|
while ( fragmentTable != nil ) {
|
|
|
|
nextFragmentTable = (*fragmentTable)->fNextFragmentTable;
|
|
|
|
if ( ((*fragmentTable)->fFontHandle >= heapStart) && ((*fragmentTable)->fFontHandle < heapEnd) ) {
|
|
|
|
RemoveFragmentTableFromCache( fragmentTable, fragmentTableCache );
|
|
|
|
fragment = (*fragmentTable)->fFirstFragment;
|
|
while ( fragment != nil ) {
|
|
|
|
nextFragment = (*fragment)->fNextFragment;
|
|
|
|
RemoveFragmentFromFragmentTable( fragment, fragmentTable );
|
|
DisposeZoneHandle( (Handle) fragment, partialFontZone );
|
|
|
|
fragment = nextFragment;
|
|
|
|
}
|
|
|
|
DisposeZoneHandle( (Handle) fragmentTable, partialFontZone );
|
|
|
|
}
|
|
|
|
fragmentTable = nextFragmentTable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: PackStringClass( platformID, scriptID, languageID )
|
|
|
|
Purpose: Pack platformID, scriptID, and languageID into a four byte integer.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
long PackStringClass( short platformID, short scriptID, short languageID )
|
|
|
|
{
|
|
|
|
return( ~((platformID << 16L) | (scriptID << 8L) | languageID) );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: UnpackStringClass( class, &platformID, &scriptID, &languageID )
|
|
|
|
Purpose: Extract a platformID, scriptID, and languageID from a four byte integer.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
void UnpackStringClass( long class, short* platformIDPointer, short *scriptIDPointer, short *languageIDPointer )
|
|
|
|
{
|
|
|
|
class = ~class;
|
|
if ( languageIDPointer != nil )
|
|
*languageIDPointer = class & 0xff;
|
|
|
|
class >>= 8;
|
|
if ( scriptIDPointer != nil )
|
|
*scriptIDPointer = class & 0xff;
|
|
|
|
class >>= 8;
|
|
if ( platformIDPointer != nil )
|
|
*platformIDPointer = class & 0xff;
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: LookupSplineTagTableIndex( splineTag, splineDirectoryPointer )
|
|
|
|
Purpose: Try to find a directory entry with a tag field equal to the splineTag
|
|
parameter. If found, return the directory table index. Otherwise,
|
|
return zero.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
long LookupSplineTagTableIndex( long splineTag, sfnt_OffsetTable* splineDirectoryPointer )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
Boolean found;
|
|
long tableIndex, tableCount;
|
|
sfnt_DirectoryEntry* tablePointer;
|
|
|
|
found = false;
|
|
tableIndex = 1;
|
|
tablePointer = splineDirectoryPointer->table;
|
|
tableCount = splineDirectoryPointer->numOffsets;
|
|
|
|
while ( (found == false) && (tableIndex <= tableCount) ) {
|
|
|
|
if ( tablePointer->tag == splineTag ) {
|
|
|
|
found = true;
|
|
|
|
} else {
|
|
|
|
tableIndex++;
|
|
tablePointer++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return( found ? tableIndex : 0 );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: GetSplineDirectoryFragmentPointer
|
|
|
|
Purpose: Return a pointer to the splineDirectory for the outline font resource
|
|
specified by the splineFont parameter. Two reads are necessary to
|
|
load the spline directory. The first read loads the directory header.
|
|
The second read loads the entire directory using the numOffsets field
|
|
of the spline directory to determine the directory size.
|
|
|
|
Warnings: QDUngetFontFrag must called using the splineFont parameter and this
|
|
function's result as it's parameters. Not doing so will result in handles
|
|
that can't be purged from the partialFontZone and will eventually lead
|
|
to an out of memory error.
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
void* GetSplineDirectoryFragmentPointer( Handle splineFont )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
Size splineDirectorySize;
|
|
sfnt_OffsetTable* splineDirectoryPointer;
|
|
|
|
splineDirectoryPointer = (sfnt_OffsetTable*) QDGetFontFrag( splineFont, 0, OFFSETTABLESIZE );
|
|
if ( splineDirectoryPointer != nil ) {
|
|
|
|
splineDirectorySize = OFFSETTABLESIZE + (splineDirectoryPointer->numOffsets * sizeof(sfnt_DirectoryEntry));
|
|
QDUngetFontFrag( splineFont, splineDirectoryPointer );
|
|
|
|
splineDirectoryPointer = (sfnt_OffsetTable*) QDGetFontFrag( splineFont, 0, splineDirectorySize );
|
|
}
|
|
|
|
return( splineDirectoryPointer );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: PartialGetFontTablePtr
|
|
|
|
Purpose: Return a pointer to a piece of data within a table. The splineFont parameter
|
|
identifies the outline font resource. The offset parameter is relative to
|
|
the start of the table and specifies where to read the data from. Length
|
|
specifies how many bytes to read. If length is -1 a pointer to the entire
|
|
table is returned.
|
|
|
|
Either tableIndex or splineTag can be used to specify the table to read
|
|
from. If tableIndex is zero, the splineTag parameter is used to lookup
|
|
the directory tableIndex. Otherwise, tableIndex is used directly.
|
|
|
|
Warnings: QDUngetFontFrag must called using the splineFont parameter and this
|
|
function's result as it's parameters. Not doing so will result in handles
|
|
that can't be purged from the partialFontZone and will eventually lead
|
|
to an out of memory error.
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
void* PartialGetFontTablePtr( Handle splineFont, long offset, long length, long tableIndex, long splineTag )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
void* dataPointer;
|
|
long readOffset, readLength;
|
|
sfnt_OffsetTable* splineDirectoryPointer;
|
|
sfnt_DirectoryEntry* splineTableEntryPointer;
|
|
|
|
dataPointer = nil;
|
|
|
|
splineDirectoryPointer = (sfnt_OffsetTable*) GetSplineDirectoryFragmentPointer( splineFont );
|
|
if ( splineDirectoryPointer != nil ) {
|
|
|
|
if ( tableIndex == 0 )
|
|
tableIndex = LookupSplineTagTableIndex( splineTag, splineDirectoryPointer );
|
|
|
|
if ( tableIndex != 0 ) {
|
|
|
|
splineTableEntryPointer = &splineDirectoryPointer->table[tableIndex - 1];
|
|
readOffset = splineTableEntryPointer->offset + offset;
|
|
readLength = (length == -1) ? splineTableEntryPointer->length : length;
|
|
dataPointer = QDGetFontFrag( splineFont, readOffset, readLength );
|
|
|
|
}
|
|
|
|
QDUngetFontFrag( splineFont, splineDirectoryPointer );
|
|
|
|
}
|
|
|
|
return( dataPointer );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: GetFontTablePtr
|
|
|
|
Purpose: Bozo routine to load an entire table into memory.
|
|
|
|
Warnings: QDUngetFontFrag must called using the splineFont parameter and this
|
|
function's result as it's parameters. Not doing so will result in handles
|
|
that can't be purged from the partialFontZone and will eventually lead
|
|
to an out of memory error.
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
void* GetFontTablePtr( Handle splineFont, long tableIndex, long splineTag )
|
|
|
|
{
|
|
|
|
return( PartialGetFontTablePtr( splineFont, 0, -1, tableIndex, splineTag ) );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: GetFontMapInfo( splineFont, index, &glyphs[0], count, &stream[0], &streamLength )
|
|
|
|
Purpose: Function used by MacExtra.c
|
|
|
|
Return bizarre function result. Two different function results are returned
|
|
based on the platformIndex parameter. If platformIndex is non-zero a packed
|
|
string class is returned by looking up the platformID and specificID from
|
|
the cmap's platformArray. If platformIndex is zero the routine attempts to
|
|
find a platform entry with a platformID and specificID equal to the platformID
|
|
and specificID values contained in the class parameter. If a match is found
|
|
the platformIndex is returned. Otherwise zero is returned.
|
|
|
|
Function Result Summary:
|
|
|
|
-1 if an error occured
|
|
zero or positive integer if platformIndex parameter is zero
|
|
packed string class if platformIndex is non-zero
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
long GetFontMapInfo( Handle splineFont, long platformIndex, long class )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
short platformCount, platformID, scriptID;
|
|
long platformIndexOrClass;
|
|
sfnt_char2IndexDirectory* char2IndexTablePointer;
|
|
sfnt_platformEntry* platformPointer;
|
|
|
|
platformIndexOrClass = -1;
|
|
|
|
char2IndexTablePointer = (sfnt_char2IndexDirectory*) GetFontTablePtr( splineFont, 0, tag_CharToIndexMap );
|
|
if ( char2IndexTablePointer != nil) {
|
|
|
|
if ( platformIndex != 0 ) {
|
|
|
|
platformPointer = char2IndexTablePointer->platform + platformIndex - 1;
|
|
platformIndexOrClass = PackStringClass( platformPointer->platformID, platformPointer->specificID, 0 );
|
|
|
|
} else {
|
|
|
|
platformIndexOrClass = 0;
|
|
platformCount = char2IndexTablePointer->numTables;
|
|
platformPointer = char2IndexTablePointer->platform;
|
|
UnpackStringClass( class, &platformID, &scriptID, 0 );
|
|
|
|
platformIndex = 1;
|
|
while ( (platformIndexOrClass == 0) && (platformIndex <= platformCount) ) {
|
|
|
|
if ( (platformPointer->platformID == platformID) && (platformPointer->specificID == scriptID) ) {
|
|
|
|
platformIndexOrClass = platformIndex;
|
|
|
|
} else {
|
|
|
|
platformIndex++;
|
|
platformPointer++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QDUngetFontFrag( splineFont, char2IndexTablePointer );
|
|
|
|
}
|
|
|
|
return( platformIndexOrClass );
|
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
Routine: ApplyFontMap( splineFont, index, &glyphs[0], count, &stream[0], &streamLength )
|
|
|
|
Purpose: Function used by MacExtra.c.
|
|
|
|
Call the appropriate cmap string mapping function based on the platformIndex
|
|
parameter.
|
|
|
|
Warnings: None
|
|
|
|
----------------------------------------------------------------------------------- */
|
|
|
|
|
|
long ApplyFontMap( Handle splineFont, long platformIndex, short* glyphPointer, long glyphCount, char* streamPointer, long* streamLengthPointer )
|
|
|
|
{
|
|
|
|
// Locals
|
|
|
|
long glyphsProcessed;
|
|
sfnt_char2IndexDirectory* charToIndexTablePointer;
|
|
sfnt_platformEntry* platformPointer;
|
|
sfnt_mappingTable* mappingTablePointer;
|
|
uint16* mappingDataPointer;
|
|
|
|
glyphsProcessed = 0;
|
|
|
|
charToIndexTablePointer = (sfnt_char2IndexDirectory*) GetFontTablePtr( splineFont, 0, tag_CharToIndexMap );
|
|
if ( charToIndexTablePointer != nil ) {
|
|
|
|
platformPointer = charToIndexTablePointer->platform + platformIndex - 1;
|
|
mappingTablePointer = (sfnt_mappingTable*) ((char*) charToIndexTablePointer + platformPointer->offset);
|
|
mappingDataPointer = (uint16*)(mappingTablePointer + 1);
|
|
|
|
switch ( mappingTablePointer->format ) {
|
|
|
|
case 0:
|
|
glyphsProcessed = MapString0( (uint8*) mappingDataPointer, (uint8*) streamPointer, glyphPointer, glyphCount );
|
|
break;
|
|
|
|
case 2:
|
|
glyphsProcessed = MapString2( mappingDataPointer, streamPointer, glyphPointer, glyphCount, streamLengthPointer );
|
|
break;
|
|
|
|
case 4:
|
|
if ( platformPointer->platformID == plat_Macintosh )
|
|
glyphsProcessed = MapString4_8( mappingDataPointer, (uint8*) streamPointer, glyphPointer, glyphCount );
|
|
else
|
|
glyphsProcessed = MapString4_16( mappingDataPointer, (uint16*) streamPointer, glyphPointer, glyphCount );
|
|
break;
|
|
|
|
case 6:
|
|
if ( platformPointer->platformID == plat_Macintosh )
|
|
glyphsProcessed = MapString6_8( mappingDataPointer, (uint8*) streamPointer, glyphPointer, glyphCount );
|
|
else
|
|
glyphsProcessed = MapString6_16( mappingDataPointer, (uint16*) streamPointer, glyphPointer, glyphCount );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
QDUngetFontFrag( splineFont, charToIndexTablePointer );
|
|
|
|
}
|
|
|
|
return( glyphsProcessed );
|
|
|
|
}
|