Printer’s Apprentice 8.1 Documentation Available Online

April 27th, 2011 by Bryan Kinkel

The documentation for Printer’s Apprentice 8.1 is now available online. It is the same content that is included with the software in the Help file.

You can find the documentation here:

http://www.loseyourmind.com/PrintersApprentice/Help/default.aspx

This project was interesting. Windows Help files (.chm) are HTML files that are compressed and indexed using a series of tools from Microsoft. I wanted the web site to use the exact same files as the CHM files. This way I have only one set of source files to edit when adding content.

I evaluated many different documentation products that produce documentation across a variety of mediums (web, print, PDF, CHM, etc). But I settled on a home grown solution using ASP.NET. There is a single master page that provides the navigation control. Each page in the help file is based on the master page and using simple file IO to read in the original HTML file and stream it back to the user. Sometimes the simple solution is the best!

Posted in .NET Framework 2.0, Printer's Apprentice | No Comments »

Printer’s Apprentice 8.00.32 Update

July 6th, 2009 by Bryan Kinkel

The next version of Printer’s Apprentice is being prepped for the beta team. Download notices should go out in the next day or so.

The next  update will have a pair of “fit & polish” features. These are nothing too serious. And they certainly did not take long to implement. But they simply make the application better.

Full Screen Toggle – This button simply maximizes Printer’s Apprentice to fill the full screen. The top title bar is hidden and the Printer’s Apprentice window covers the Windows Taskbar. The hotkey to toggle full screen mode is F11. (Microsoft Office and FireFox also use F11 for full screen modes.)

toggle1 toggle2

toggle3

This feature is great for when you really want to see your fonts blown up large. Or for when you are working with a client on font selection over a shared monitor.

Sorting Glyphs (Arrows) – Like Windows Explorer, Printer’s Apprentice now uses the built in sorting arrows in all the listviews throughout the application.

This should have been in the application a long time ago. However, the .NET listview control does not expose the arrow functionality directly. So the implementation uses Windows API calls. The code was not difficult at all. But it kept getting bumped down on the To Do list.

sort-installedfonts

Posted in .NET Framework 2.0, Printer's Apprentice, Programming | No Comments »

Printer’s Apprentice Update

April 22nd, 2009 by Bryan Kinkel

Now that Postscript printing is out of the way, I”m working on performance issues for Printer’s Apprentice.

One bottleneck in the system is reading fonts with the Font Files and Font Groups tabs.

When PA displays a list of fonts, it does not just show the file name and size. It also has to show the proper font name. The font names are stored deep inside the TrueType file structure in a series of tables. So when listing the the fonts in a folder, PA opens each file, reads in the file name and other data, then close the file. If you have hundreds of files in a folder, this can take a few (annoying) moments.

To get around this delay, I’m implementing a very simple font cache mechanism. The cache is an XML file, stored in %appdata%\printer’s apprentice\fontcache.xml, with the following structure.

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <fontcache>
    <path>c:\fonts\ttfonts\a_c\tt0035m_.ttf</path>
    <size>47356</size>
    <fontfamily>Bodoni Bk BT</fontfamily>
    <fullfamilyname>Bodoni Book BT</fullfamilyname>
    <format>1</format>
    <outline>1</outline>
    <bold>0</bold>
    <italic>0</italic>
    <weight>400</weight>
  </fontcache>
</NewDataSet>

I’m still working with the code and .NET calls to see how I can compact the XML. But the basic idea is in place.

When Printer’s Apprentice reads a directory, it first checks the cache for a match on name and file size. If it finds a match, then the font data is right there. Otherwise we need to read the TTF/PFM/OTF data directly. Any new data is saved in the cache as well.

Here are some very preliminary benchmarks for reading in a few folders of TrueType and Postscript fonts. The “initial read” is the first time PA examines a folder of font file. Since it is they are not in the cache, each file is opened up and examined. The “cached read” is the time for subsequent reads of the folder. The files are all found in the cache and don’t need to be opened. The data is right there in the cache.

Folder contains Initial Read Cached Read
145 TrueType fonts 5 seconds 2 seconds
125 Type 1 fonts 10 seconds 2 seconds
502 TrueType fonts 10 seconds 6 seconds
500 Type 1 fonts 20 seconds 6 seconds

This is all still in the early stage of development. I’m still working with the storage format and benchmarking. But the work is moving forward. Stay tuned.

Comments? Questions? helpdesk at lose your mind dot com.

Bryan

Posted in .NET Framework 2.0, Fonts, Printer's Apprentice | No Comments »

Fonts & Windows 7

February 13th, 2009 by Bryan Kinkel

While I do have a copy, I have not yet installed the Windows 7 beta. But I have been closely following the daily reports in the blog world.

And today we have a report about font support in Windows 7 directly from the Engineering Windows 7 blog.

Advances in typography and text rendering in Windows 7

This is a good read. In particular check out the section titled Fonts and Font Management.

The author does make a note of the current Windows graphics system having “not fully embraced OpenType for its mainstream usage of text.” Oh how true this is.

The GDI+ layer, used by .NET, does not support Type 1 or OpenType fonts with Postscript outlines. And that is why I have to start working on some sort of kludge to get Type 1 fonts rendered on the printed page in Printer’s Apprentice 8.0.

Posted in .NET Framework 2.0, Fonts | No Comments »

Windows XP SP3 & PrivateFontCollections

May 13th, 2008 by Bryan Kinkel

As a follow up to my multiple posts about memory corruption problems with .NET PrivateFontCollection objects, I installed Windows XP SP3 on a virtual machine today.

To my surprise, XP SP3 fixed the problem and I could not reproduce the corruption issue with my test rig.

The screen below shows that my PFC Stress App has created and destroyed a PrivateFontCollection object 34 times without crashing. With XP SP2, the app would crash after only a few loads.

pfc-sp3

Printer’s Apprentice uses a PrivateFontCollection object for printing. So I added some logic to dispose the object only when running XP SP3 or better (including Vista). Otherwise the .NET garbage collector will (hopefully) eventually clean up the memory.

Posted in .NET Framework 2.0, Printer's Apprentice | 1 Comment »

Windows XP SP3 & PrivateFontCollections

May 8th, 2008 by Bryan Kinkel

According to Microsoft Knowledge Base 946480, the PrivateFontCollection memory corruption problem fix is included in Windows XP PS3. I will be installing the service pack to verify.

Posted in .NET Framework 2.0, Microsoft | 1 Comment »

XP Service Pack 3 & PrivateFontCollections – Do we have a fix?

October 11th, 2007 by Bryan Kinkel

This is a follow up to my original post about a PrivateFontCollection bug in Windows XP. According to a post at msbetas.org, Windows XP Service Pack 3 will include the hot fix for 901026. This is very good news.

XP SP3 Fix List at msbetas.org

Memory corruption or an access violation may occur in a custom application that uses the PrivateFontCollection object in Windows XP

http://support.microsoft.com/kb/901026

Posted in .NET Framework 2.0, Fonts, Microsoft, Printer's Apprentice | 1 Comment »

PrivateFontCollection – Access Violation Errors

October 2nd, 2007 by Bryan Kinkel

About two weeks ago I started working on the “Print All Fonts In Path” feature in Printer’s Apprentice. This feature print catalogs and sample sheet for all fonts in a selected folder tree. And the fonts are typically not currently installed in Windows. (note: Previous versions could print catalogs. But v8 will print both catalogs and sample sheets.)

Once I got the whole process working start to finish, I started to get these errors when the Print dialog box was closed.

The image on the left is the error as it occurs in Visual Studio 2005 (VS). And on the right is what happens when the compiled executable runs by itself. The exception detail follows below.

paxp-vs2005-1 paxp-exe


System.AccessViolationException was unhandled
  Message=”Attempted to read or write protected memory. This is often an indication that other memory is corrupt.”
  Source=”System.Drawing”
  StackTrace:
       at System.Drawing.SafeNativeMethods.Gdip.IntGdipDeleteFontFamily(HandleRef fontFamily)
       at System.Drawing.SafeNativeMethods.Gdip.GdipDeleteFontFamily(HandleRef fontFamily)
       at System.Drawing.FontFamily.Dispose(Boolean disposing)
       at System.Drawing.FontFamily.Finalize()

How nice. This bug became the problem of the week.

The first place to start is an understanding of the GDI+ and PrivateFontCollection (PFC) objects. Applications based on .NET use GDI+ for drawing and printing. GDI+ is the successor to the existing Win32 GDI subsystem. It makes programming complex text and graphic layouts much easier and gives us print preview objects built right into the platform. GDI+ also includes it own font management functions and you need to use them if you use the GDI+ PrintDocument and PrintPreview controls. (GDI+ will not render text in a font loaded with the Win32 AddFontResource() function.)

To draw a string using an uninstalled font, you first load the font into a PrivateFontCollection. This class, from system.drawing.text namespace, is a wrapper around an object of the same name in Microsoft’s GDI+ library. It allows the developer to use uninstalled fonts in an application. For example, a developer might ship a proprietary bar code font along with his mailing label application.

Printer’s Apprentice uses a globally scoped PFC to manage fonts on the printed page. The Print All Fonts in Path function goes through these steps to generate a catalog:

  1. Walk the directory path to generate a list of TrueType and OpenType fonts.
  2. Add each font to a globally scoped PFC – oPFC.AddFontFile(pFileName).
  3. Show the Print Preview window. Text functions create and use fonts from the oPFC object. A PrintDocument object does the heavy lifting and draws the layout on a PrintPreview control or printer device.
  4. Once the dialog closes, the PFC is disposed.
  5. Boom – the app crashes.

It was easy to narrow the error to the lines below. The stack trace clearly points to disposing the PrivateFontCollection. What was strange is that VS did not halt on the actual line. It would fail a few moments after the line was executed.

oPFC.Dispose()oPFC = Nothing

But the PrivateFontCollection.Dispose() call gave me some ammunition to search with. And I was eventually lead to MS Knowledge Base article 901026.

Memory corruption or an access violation may occur in a custom application that uses the PrivateFontCollection object in Windows XP
http://support.microsoft.com/kb/901026

What is interesting about the article is that it states that the corruption occurs when the application has outstanding references to GpFontFamily objects. To me, this means the code loads a font to a PFC, creates a Font object, renders some text, then disposes the PFC without disposing the Font object. I then spent a lot of time combing through code trying to find Font objects that were not properly disposed. I even loaded up SciTech’s .NET Memory Profiler looking for leaks. No luck. The app still crashes.

I then built a demonstration application in an attempt to duplicate the problem in a very simple environment. PFCTest.exe simply reads a directory of TTFs, adds the fonts to a PFC and then disposes the fonts. The fonts are not used at all in the application. It runs and crashes as expected under Windows XP. With Vista, it runs fine. I was able to read the fonts and dispose the PFC over 100 times. Look at the execution count label in the screenshots below.

pfc-xp-full pfc-vista

 
Here is the Visual Studio 2005 project: pfctest.zip

My next step was to obtain and install the 901026 hotfix. Since it is a hotfix and not part of a regular Windows XP update, I had to request it from Microsoft. They got the fix to me rather quickly. But I could not install it.

pfc-hotfix-bad

What next? I need to get in touch with Microsoft again about this and see if I can get a setup package that will install. The package they sent appears to be for Windows Server 2003.

But a larger issue looms. This is clearly a bug in the GDI+ subsystem. When will it get fixed? Will a fix be included in XP Service Pack 3? And it is not the first bug I have run into… If I take out the oPFC.Dispose() code, then Printer’s Apprentice will have a slow memory leak. Until I get a resolution from Microsoft, it will have to be my solution for now as I have to continue working on other features. Yuck.  — Bryan

Posted in .NET Framework 2.0, Fonts, Microsoft, Printer's Apprentice | 2 Comments »

Printer’s Apprentice 8.0 Screens – Uninstall Fonts

June 14th, 2007 by Bryan Kinkel

As promised in an earlier posting, here are two screenshots from the Uninstall Fonts dialog box. Click the see the full size images.

I’ve been experimenting with the gradient colors in the dialog box header. For now, the gradient colors a similar to those used in the Windows Live product line (Messenger, Writer). So the gradient goes from RGB(0,119,166) to RGB(155,244,255). I like the colors. But I still need to check on them in Vista.

The rounded corner gradient comes from Nick Waelti and his excellent AlphaGradientPanel control for Windows Forms based projects. (Control used with permission from the author.)

The screenshots below use Vista style icons. But the interface has an option for XP icons as well.

uninstall1

uninstall2

Posted in .NET Framework 2.0, Printer's Apprentice | 2 Comments »

Printer’s Apprentice Objects

April 24th, 2007 by Bryan Kinkel

One of the goals for the Printer’s Apprentice rewrite is to significantly simplify the code base. The code in the current version, 7.58, has roots going back to 1992 and Visual Basic 1.0. Much of the code is overly complex and function, rather than object, oriented.

Visual development environments make it very easy to build a great UI and then integrate code into the events such as Button_Click. Then next thing you know you have a great looking form with a ton of code tucked into the events.

That is is precisely how the code in Printer’s Apprentice evolved. Bad, bad, bad. So I’m working to change that approach with the new version. What I want to do with this posting is give you an idea of how the user interface objects consolidate code and how they communicate with each other.

Lets take a look at two objects, ctlInstalledFonts and cEnumFonts. ctlInstalledFonts handles the UI for selecting installed fonts in Printer’s Apprentice. cEnumFonts is a data layer that does the grunt work of reading fonts from the OS, linking them to registry entries and so forth.

On the left is the design view of the UI object. On the right are simplified class diagrams for the ctlInstalledFonts and cEnumFonts.

          

 

cltInstalledFonts only job is to present the UI for installed fonts. It does not actually enumerate or read installed fonts, that is a data operation handled by the other object, cEnumFonts.

The Fields section lists controls, properties and data entities in the control. The actual control contains many more entities. I’m only showing a few important ones for this discussion. 

ctlInstalledFonts Fields
_EnumFonts Private instance of a cEnumFonts object.
lvInstalled Listview control to display fonts.
PropertyGrid PropertySheet control below the listview. This displays more details about a font than can be displayed in the listview.
mnuContext Context menu that appears when the user right clicks a font in the listview.

Again, cEnumFonts is what actually queries the system and returns the list of fonts to ctlInstalledFonts.

cEnumFonts Methods
CountFonts Gets an initial count of the fonts installed on the system.
EnumFontFamilies Function used by the Win32 EnumFontFamiliesEX() function. This is what steps through each font on a system.
ReadFonts A sub that starts the font enumeration process.
cEnumfonts Properties
FontCount Number of fonts that were enumerated.
FontList An array of fonts that were enumerated.
PropertyGrid The handle of the window listing the fonts.
IncludePostscript Do we include Postscript based fonts or not?
cEnumfonts Events
FontEnumStart Triggered when a font family is about to be read.
FontEnumFamilyCreated Triggered when a font family is read and created.
FontEnumEnd Triggered when reading a font family is complete.

When Printer’s Apprentice starts, the main form creates an instance of ctlInstalledfonts. It in turn directs its private cEnumFont object to examine the system font list.

 'walk the font list
 ctlInstalledFonts._EnumFonts.ReadFonts()

As ctlInstalledFonts._EnumFonts walks through the font list, it triggers the following events for each font that it reads.

 Public Event FontEnumStart(ByVal pFaceName As String)
 Public Event FontEnumEnd(ByVal pEnumIndex As Integer, ByVal pFontCount As Integer)

These events allow the calling form to modify the user interface as events are triggered in the ctlInstalledFonts._EnumFonts object. For example, by hooking into the events I can update the splash screen and show progress as Printer’s Apprentice loads.

Using events in a UI control also makes it easy for one menu handler to process selections for both the main window menu and context menus. The main window and ctlInstalledFonts both have a Print menu.

  

 ctlInstalledFonts has a series of customs events that all have the same signature as a standard menu call. Rather than handling print code right in the menu, the mnuPrint.Click() handler instead raises the event.

 Public Event emnuPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
 Public Event emnuUninstall_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
 Public Event emnuProperties_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
 Private Sub mnuPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuPrint.Click
    RaiseEvent emnuPrint_Click(sender, e)
 End Sub

And back in the main form, a single handler processes the Print selection for both menus. 

 #Region "File menu"
   Private Sub mnuFilePrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
     Handles mnuFilePrint.Click, ctlInstalledFonts.emnuPrint_Click, ctlFontFiles.emnuPrint_Click
     Call Me.PrintFonts()
   End Sub #End Region 

So rather than having print code scattered around the application, I use a PrintFonts() call inside a menu handler that processes the Click event for multiple menus.

This approach is certainly reducing the amount of code in Printer’s Apprentice.

Posted in .NET Framework 2.0, Printer's Apprentice, Programming | No Comments »

« Previous Entries