Often 'X doesn't work' in the docs actually implies 'We couldn't get X to work' :-)

by Michael S. Kaplan, published on 2007/11/07 10:01 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2007/11/07/5958318.aspx


It is often the case that code does even more than the developers of the code describe, so much so that by the time they are done describing the limitations that the documentation writers lay out and someone else finds out how much more is possible, there is little one can do but shake one's head and wonder if the original team knew what the code could really do and felt it would be too hard to describe, or whether they would be just as surprised at the later contribution.

Or what one of their own members was able to later describe!

Like the other day, when Irfan asked:

Hi All,

One of my Customer has a windows application(VS2005, VB.NET) where they are trying to print the Malayalam language string (Kartika font). As recommended they are using the TextRenderer class to view the string and it works fine.

It mentioned in the MSDN that
TextRenderer is not used for printing:

    The DrawText methods of TextRenderer are not supported for printing. You should always use the DrawString methods of the Graphics class

So to print the Malayalam string we have following two options

1.   We can save the string in a bitmap image and print it using the Graphics.DrawImage function.
2.   We can directly print the string from textbox using the Graphics.DrawString.

Now when we print with the first option it does print but the output looks like a dotmatix printer output.( this is rejected by the customer’s client) and now when we tried to use the second option it gave an error "A generic error occurred in GDI+"

Now the conventional wisdom has always gone along with the way that Irfan laid out the options.

And I certainly never have (either in some of the previous times I have talked about TextRenderer here in the blog or in conversation or email) suggested anything beyond this before (other than perhaps changing the image type to be something less grainy than a bitmap!).

But colleague Aldo pointed out the article from MSDN Magazine entitled Text Rendering: Build World-Ready Apps Using Complex Scripts In Windows Forms Controls by Miguel A. Lacouture (a developer on the WinForms team!), with a section entitled Printing with TextRenderer not listed under the Limitations of TextRenderer section earlier in the article -- a section that was quite eye-opening:

When working with System.Drawing.Printing, you are usually interested in handling the PrintPage event of the PrintDocument object. You can use the Graphics object of the PrintPageEventArgs in the same way you use the Graphics object obtained from the PaintEventArgs when handling a control's paint event. In many cases, you want to use a common method to draw—for example, drawing into a Form, the printer, and a print-preview dialog box. This ensures consistency between what the user sees on screen and on the printed page.

This technique, however, does not work with TextRenderer. The reason is that the Graphics object in the PrintPageEventArgs object is set up with the resolution of the printer and also works with a different coordinate unit—it is usually set for the coordinate unit to be hundredths of an inch. How does it work for the Graphics object? That is where GDI+ displays its beauty. GDI+ is a device-independent graphics library and knows how to scale units properly in this case. TextRenderer assumes all units are at 100 percent. In other words, no scaling is needed.

To make TextRenderer work with the printing API, unit scaling needs to be performed beforehand. Figure 5 shows how to scale a Point and a Font to be used with TextRenderer when the Graphics object comes from the printing library. Units are converted from hundredths of an inch to pixels using the resolution of the device, which is obtained from the Graphics object DpiX and DpiY properties.

In Figure 6, the printing flag is set to true in the printDoc_Print-Page event handler method for the PrintPage event, and false in the control_Paint event handler method for the Paint event. The PaintWorker method checks this flag and, if printing, calls the scaling methods in Figure 5.

Even though this approach solves the problem encountered when using TextRenderer for printing and print-previewing, it does not guarantee that you will obtain the same WYSIWYG results you get with the Graphics class. The main reason is that the GDI character-spacing and word-breaking algorithm is not linear—the text rendered using the scaled values may end up with a different layout. Other reasons include the loss of precision when scaling the values and the possibility of obtaining a scaled font that is different from the intended scaling. This can occur if the intended scaled font does not exist and the font-mapping algorithm selects what it thinks is the closest match.

That changes everything! 

This information really knocks the documentation right over, doesn't it?

One has to wonder if the originally documented limitation was added after some tester found the bug and they just decided it was better to document that things don't work and call it a day? :-)

I have never been more happy to be mistaken about something than after I read that article, with its reminder that folks here at Microsoft are often:

The reminder that saying something doesn't work is often a translation for "we couldn't get it working here". :-)

Very cool! Someone remind me to buy Miguel A. Lacouture a round of whatever he's drinking some day....

 

This post brought to you by(U+0d15, a.k.a. MALAYALAM LETTER KA)


# Gene on 7 Nov 2007 4:32 PM:

Sigh. Printing gets the short end of the stick just about everywhere except maybe Apple.

In UNIX, if you're lucky you get "everything's a Postscript printer" (except then of course half the time they generate invalid Postscript) and if you're not, you get "everything's an ASR-33 TTY"

More on topic, it seems "not supported" is code for "making it work is non-trivial and we're not going to explain it here". So who's going to submit a bug on the MSDN docs, and are they going to include example code?  :-)

(I do have to say that MSDN article has some of the best design & layout I've ever seen on a web page.)

# Gene on 7 Nov 2007 4:35 PM:

Oh, and "Text-rendering libraries must excel at rendering text" is priceless. :-)


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