Technical Q&As


Changing Size of sfnt Cache (12-April-98)


Q I'm experiencing problems with some of my big sfnt fonts (> 128k). Text in these fonts often gets rendered in Geneva, or not at all. Do you know something about this?
A Yes, unfortunately. If a sfnt resource is bigger than 128k, the FontManager does not load it entirely, but only in pieces (as required by the TrueType scaler) via ReadPartialResource calls. For performance reasons, the TrueType scaler uses a cache for the font fragments, which gets allocated in the System heap at boot time. Before MacOS 8.0, the cache size was 10k, which appeared to be enough for the TrueType fonts known at the time when the cache size was determined (and when TrueType fonts wanted to be supported on Macintoshes with 2MB of RAM). Meanwhile, sfnt fonts became more sophisticated, and their tables bigger and bigger, and 10k just is not enough any more. Since MacOS 8.0, the cache size is 48k; but this still may not be enough for very special fonts (e.g., sfnts for 2-byte scripts, when WorldScript II is not installed). Fortunately, there is a way to fix the problem and change the size of the sfnt fragment cache. Ideally, this should happen as soon as possible at system startup; so you may want to use the code below inside a little extension that does the work.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// File: FontFix.c
//
// Calls InitializePartialFonts() with a more reasonable size.
//
// kMinimalPartialFontZoneSize in the system used to be 10 * 1024,
// which is not enough. 
// On a system where the PartialFontZone already is big enough,
// InitializePartialFonts() doesn't do anything.
// Only if the existing PartialFontZone is smaller than our new
// kMinimalPartialFontZoneSize (or if there is none), the InitializePartialFonts 
// routine allocates and initializes a new one, and properly disposes 
// of the previous one (if there was one).

#include <Types.h>
#include <ConditionalMacros.h>
#include <Resources.h>


enum {  kMinimalPartialFontZoneSize = 0x0000C000,   // 48K
        kMaximalPartialFontZoneSize = 0x00080000    // 512K
        };

extern pascal OSErr InitializePartialFonts (UInt32 partialFontZoneSize)
        THREEWORDINLINE(0x303C, 0x000F, 0xA854);

//-------------------------------------------
void main(void)
{
	UInt32	size = kMinimalPartialFontZoneSize; // default
	Handle 	h;
	
 // Debugger();
    
    h = GetResource('pfcs', 0);
    if (h != NULL)
        {
        size = **(UInt32**)h;
        if (size < kMinimalPartialFontZoneSize)
            size = kMinimalPartialFontZoneSize;
        else if (size > kMaximalPartialFontZoneSize)
            size = kMaximalPartialFontZoneSize;
        }
    (void)InitializePartialFonts(size);
}


-- Ingrid Kelly
Worldwide Developer Technical Support

Technical Q&As
Previous Question | Contents | Next Question

To contact us, please use the Contact Us page.