/* 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): 7/7/92 CSS Roll-in Reality Changes: <7> 7/4/92 DTY #1034875 : 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. 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. 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 // 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 // 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 ); // 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 ); }