views:

1118

answers:

3

Hi,

I am trying to generate a PDF using XSL(XML-FO) to transform a generated XML from a database.

Because of complex rules in terms of paging for this document, calculations are done in determining the page breaks when I generate the XML that will be consumed by the XSL. I have noticed that I've been getting inconsistent results with these calculations. For instance, the required print area in terms of height is 9 inches which I then convert to points by multiplying it by 72 (being 72 points per inch) = 648 points.

So for every line, I use MeasureString to get the height of the line which I then subtract from 648 to see if there are still available space to print the line. But whenever a page break is determined, there would be a large whitespace that is left at the bottom. It is as if the 648pt conversion is wrong. Now I am also concerned that the height being returned by the MeasureString method may also be wrong.

I apologize for the long post but I appreciate any input/suggestion as to what I might be doing wrong.

Thanks a lot!

+2  A: 

I think the biggest problem is that you're using GDI methods to measure a string that will be displayed in a PDF. That's just not going to be accurate enough. (Even if you get the fonts identical, they use different rendering techniques from what I remember.)

So, you ought to try other forms of calculation. One simple first step would be to estimate the characters per line and then the height of each line as it would come out in the PDF. Then, just use those numbers. Once that is close, you can improve the technique for estimation by paying attention to specific characters. (You probably don't want to get to the level of calculating kerning.)

Another technique could be to do something that I worked on in a past project. Using iTextSharp, we had to add hollow text diagonally across a page (as a sort of watermark). Since the text was unknown, we guessed at the original font size. Then the code went into a loop where it would measure the size of the rendered text, and adjust it up or down until it was just the right size to fill the page without clipping any of the text. (All of this guessing and measuring was done with iTextSharp.)

John Fisher
Sorry, it took so long to get back to you guys. I had to do the estimating technique. I believe I'm getting close. Thanks!
Jaime
A: 

I assume that you are using the method MeasureString method on the System.Drawing.Graphics class. You have to set the PageUnit property to GraphicsUnit.Point to get measurements in points.

XSL-FO will most likely not render in the same way as GDI+. In particular algorithms for wrapping text will be different.

However, assuming that the PageUnit is correct and that you have a simple layout that doesn't involve text that has been wrapped you may have overlooked something obvious while estimating the size of the PDF produced by XSL-FO. Perhaps, you can try to change the page size from 1 to 9 inches in intervals of 1 inch. You can then use a ruler to measure the excess whitespace and try to determine the relation between page size and excess whitespace. You should then revisit your code to figure out where you have a bad assumption about the size of the text.

Martin Liversage
Thanks for reply Martin! I appreciate the input.
Jaime
A: 

I had a very similar problem a couple of years ago.

What I found on my own project was that I got much better results using the old Win32 gdi functions for text metrics (http://msdn.microsoft.com/en-us/library/dd144821(VS.85).aspx) through P/Invoke. It returns quote different results than the GDI+ MeasureString. They were much more consistent with what were seeing in the PDFs.