Content-Length: 7662 Content-Type: text/html Font Ids

Font Ids

Font ids can cause no end of problems if they are not managed correctly. Unfortunately here as well there is just not sufficient documentation of the big picture. Each process can have up to 255 logical font ids in existence at once. Since font ids are associated with a presentation space, and most presentation spaces are cached and therefore have short lifetimes (usually just for a WM_PAINT), the maximum number of font ids is usually not an issue. Other applications, such as those which create persistent presentation spaces or more complex ones that have separately developed black box subsystems or that have multiple drawing threads, correct management of font ids is important.

The simplest application is one that never uses any other font than the default system proportional font. Such programs have no font id management issues because the 0th font id always magically exists. For more complex software the two biggest problems with fonts are that multiple, separately developed, subsystems fight over the same ids and/or the leakage of font ids. The first will create weird problems because creation of logical fonts will fail (due to the id being in use by someone else) or logical fonts will be destroyed behind the back of someone who is using it. The second will eventually bring the application to an eventual, often non-obvious demise.

Font Id Management

The first step in font management beyond just using the system proportional font is to define a set of global defines for the fonts to be used by the program. If only one thread does all painting via cached presentation spaces, using font ids set up and then torn down all within the WM_PAINT code, then this scheme will work fine and all windows can share the same logical font ids without any conflict. It's simple and easy to understand, as long as the program is simple.

Once a program starts creating persistent presentation spaces, which can cause font ids to be in use outside of WM_PAINT code, or using multiple GUI threads, which can possibly have font ids in use simultaneously, the issue of font id management needs to be more formalized. Though a program can certainly provide its own font id management system, there is one built into PM that works well enough. You could though improve upon it if you felt it worth doing.

The GpiQueryNumberSetIds() API will return the current number of font ids in use by the process (which are also used for custom patterns by the way, so this number may not just reflect fonts). The GpiQuerySetIds() API will return information into 3 separate arrays (confusingly allocated as a single block of memory though) that tell you about the font ids in use by the process. Using these two APIs, you can determine what ids are currently in use and, by extension, figure out one that is safe to use.

ulGetNextId()

The easiest way to use the PM font id management APIs is to write a function/method named, for instance, ulGetNextId(). It will find and return the next available id using the APIs mentioned above. The only catch here is that, if you have multiple GUI threads or are writing general purpose code that might have to handle that situation, you must make the finding of a new id, and its being put into use, an atomic operation that is protected by a semaphore. The reason for this precaution is that GpiQuerySetIds() API doesn't care whether you've checked and found an id you liked. It only knows which ones are in use. If you use it to find an unused id, then another thread gets scheduled before you get the id into use and calls ulGetNextId(), it would get the same id. One of them would later lose when trying to create a logical font with that id, causing errors from weird displays to outright crashes.

So you really need another layer of code above the ulGetNextId() call. You need to provide APIs that lock a common semaphore, get an id, create logical fonts or custom patterns, then release the semaphore. This synchronization will insure that your management of font ids are thread safe. In most programs, just the natural synchronization of PM's message passing architecture will insure that the semaphore is not actually ever needed. But even in single threaded programs its just safer to do that small amount of work and never worry about it again.

Of course, none of this helps if you must link to 3rd party code which chooses not to play with you. It cannot know ahead of time what your locking scheme will be so you should assume (unless told otherwise) that it will probably use font ids (if at all) in the most optimistic manner, as discussed above. If you are working from some common base library code it should definitely provide such an API for all to use.

Copyright Notice | Reply to Author | Search | Section Index | Previous Page | Next Page

If you see a problem with this web site, contact edm2_eds@iqpac.com.