One man's intentional design is another man's heinous bug: GDI+ edition

by Michael S. Kaplan, published on 2011/06/01 07:01 -04:00, original URI:

Font installation is a complex and oftentimes touchy issue with a lot of people both inside and outside of Microsoft.

Maybe I should explain why I am making such bold statements. :-)

It started with a question that was asked nearly five years ago:

The customer is finding that after he temporarily installs fonts using AddFontResource (which only adds the font for the current session), then his .Net application (which, of course, is using GDI+) does not detect this newly installed font.

This is expected behavior, and the reason is twofold…

1 – The font is not permanently installed by AddFontResource unless you also add the font to the registry.  This is well documented.

2 – GDI+ (and thus System.Drawing) does not dynamically recognize fonts that are installed while the app is running (even if they *are* permanently installed).  Furthermore, there is no way for a running GDI+ application to force the InstalledFontsCollection to refresh itself.  The only solution is to restart the app, or, to add the desired font to a PrivateFontCollection instead (if the program can “know” that the font is available).

Now in this case, the customer strongly felt that #2 is a pretty bad bug.

Though the truth is that it is by design -- and something that both GDI and GDI+ have in common.

First the GDI side, explained by Michael Warning, long-time virtual demigod of GDI knowledge who helped me tremendously back in the MSLU days with GDI issues:

Just to be clear, as far as GDI is concerned “installing” fonts via registry updates and “registering” fonts via AddFontResource are logically separate operations.  Unfortunately many people think of these as one operation.

GDI will pick up dynamic font registrations and once AddFontResource returns those fonts will be available for use immediately session-wide.  GDI does not however watch for registry changes and do anything when the registry is updated.  If only the registry is updated there will be no effect until the session gets restarted. 

Actually to be overly detailed, GDI never scans the fonts key in the registry.  Other pieces of the system do that and (essentially) call AddFontResource on the user’s behalf.  In this way you could technically argue that there is no such thing as font installation in a pure GDI sense.

Now GDI+ has a different design, but it shares with GDI one thing -- the fact that its recognition of installed fonts is done by a process that happens only at initialization time (in the case of GDI that other process never checks the registry again, in the casse of GDI+ the initialization code never runs again).

Workarounds are where the similarity seems to break down a little, though.

GDI's workaround is that anyone can can call AddFontResource and then the font is available session-wide.

But for GDI+ there is no way to add yourself to the universe of the InstalledFontCollection; if you want to use the font post-init, you have to treat it as a private font within the session via the PrivateFontCollection.

I suppose one can find enough similarities and differences in the two processes to either fully support the notion that the GDI+ behavior is by design or the notion that it is a terrible bug.

But for me, the fact that GDi+ is in maintenance mode means there can't be a very good chance of either changing the design or fixing core bugs that would have such sweeping effect.

I don't use GDI+ anyway; it doesn't have the script support I need. So I think we can probably declare this issue done at this point....

RandomReader on 1 Jun 2011 11:19 AM:

Isn't that what the WM_FONTCHANGE message is there for?

Michael S. Kaplan on 1 Jun 2011 11:59 AM:

GDI+ has no window message loop, and GDI font management works at lower level than the Windows Manager....the message is so apps can do things.

Please consider a donation to keep this archive running, maintained and free of advertising.
Donate €20 or more to receive an offline copy of the whole archive including all images.

go to newer or older post, or back to index or month or day