Paint.NET v3.5 – Better font handling, and performance. Again.

Last Thursday I release a new alpha of Paint.NET v3.5, build 3450. I have rewritten the way that fonts are handled for and by the Text tool. Even if you don’t use the Text tool much, you will still notice some improvements! (see the bulleted list below)

In previous versions of Paint.NET, there are two forms of text rendering supported. The first and the default is called “Smooth”, which utilizes GDI+* to render text. The second is called “Sharp”, and uses GDI. For both, GDI+ is used for font enumeration through the classes in the System.Drawing namespace. Over time, GDI+ has proven to be a poor system for font handling. It has been the cause of many crashes, as GDI+ has a tendency to crash or trample on memory when it encounters fonts that are “bad” (although bad is relative – the font itself may be perfectly fine!). This has led to some people being completely unable to use Paint.NET through no fault of their own.

As a result, I have banished GDI+ from the Text tool. The new builds of Paint.NET are using GDI exclusively for font discovery and text rendering, a change that was substantial in the amount of code that was required and the amount of research that had to be done to make sense of it all. If you’d like to get an appreciation of the depth of the subject, you should check out chapters 14, “Fonts”, and 15, “Text”, of the book, Windows Graphics Programming: Win32 GDI and DirectDraw (Hewlett-Packard Professional Books).

The new typography system in Paint.NET has been designed so that I can plug new text rendering technologies into it. Right now it only supports GDI. For the meantime this means that the choice between “Sharp” and “Smooth” is not available. My next step is to add support for two more text rendering systems, FreeType and DirectWrite (for Windows 7 users**). The former will step in to provide the “Smooth” renderer, and the latter will be added under the name “Enhanced” (or some appropriate name).

In the meantime, you’ll still realize the following benefits in the latest alpha:

  • No more “missing” fonts. GDI+ doesn’t support some fonts, notably bitmap, vector, and certain OpenType fonts. I don’t know why. You’ll notice that the new versions of Paint.NET now has a “complete” font list.
  • Improved startup performance. It’s ironic that I was telling my manager at work the other day, “Paint.NET v1.0 had poor startup performance – in fact, it was enumerating all the system fonts at system startup, but it no longer does.” Well, because of a bug in my layout code for the toolbar, Paint.NET v3.36 was still doing this! I fixed the bug, and Paint.NET v3.5 now properly defers this to later. I’ve measured the improvement in startup performance at about 15%*** on my systems, and if you have a “lot” of fonts you will no doubt see an even bigger improvement. This is in addition to the already improved startup performance of v3.5 versus v3.36!
  • Improved stability. Like I mentioned earlier, GDI+ often crashes when it runs into “bad” fonts (subject to GDI+’s definition of “bad”). Or, it has bugs that lead it to trample on memory it does not own, resulting in crashes which get attributed to the wrong code. GDI does not have this problem. Or, at the very least, if it runs into “bad” fonts, I now control the code that deals with this. I can then make it do something other than crash.
  • Installing new fonts. Previously, Paint.NET needed to be restarted for it to recognize any new (or deleted) fonts. I now place a FileSystemWatcher object on the system fonts directory and refresh the toolbar’s font list when changes are detected. There is also a shortcut in the Utilities menu to open the Fonts directory, which will be very useful for helping answer the question that is asked with surprising frequency on the forum: “How do I add fonts?”

* The Wikipedia article states that in the Windows XP timeframe, GDI was deprecated in favor of GDI+. This is not true, although it may have been the altruistic intent at the time.

** This will eventually be supported on Windows Vista as well. 

*** On my personal system, the difference is 0.577 seconds versus 0.405 seconds, as reported by Process Explorer. This is not a formal or exhaustive performance analysis. The precision and accuracy of Process Explorer is not at the millisecond level, hence me rounding all the way down to 15%. The system is an Intel Core i7 920 overclocked to 3.6GHz running Windows 7 RC build 7100. Another system, a Core 2 Quad Q6600 2.4GHz system running Windows 7, reported values of 1.0 second versus about 0.8 seconds, respectively.