计算格式化字符串的宽度和长度 C# 中的高度
我正在尝试使用 XSL(XML-FO) 生成 PDF,以转换从数据库生成的 XML。
由于该文档的分页规则很复杂,因此当我生成将由 XSL 使用的 XML 时,需要进行计算来确定分页符。 我注意到这些计算得到的结果不一致。 例如,所需的打印区域高度为 9 英寸,然后我将其乘以 72(即每英寸 72 点)= 648 点来转换为点。
因此,对于每一行,我使用 MeasureString 获取该行的高度,然后从 648 中减去该高度,以查看是否仍有可用空间来打印该行。 但每当确定分页符时,底部都会留下很大的空白。 就好像648pt转换是错误的。 现在我还担心 MeasureString 方法返回的高度也可能是错误的。
我对这么长的帖子表示歉意,但我感谢任何关于我可能做错的事情的意见/建议。
多谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为最大的问题是您使用 GDI 方法来测量将在 PDF 中显示的字符串。 这只是不够准确。 (即使您获得相同的字体,它们也使用与我记忆中不同的渲染技术。)
因此,您应该尝试其他形式的计算。 一个简单的第一步是估计每行的字符数,然后估计 PDF 中每行的高度。 然后,只需使用这些数字即可。 一旦接近,您可以通过关注特定字符来改进估计技术。 (您可能不想达到计算字距调整的水平。)
另一种技术可能是做我在过去的项目中做过的事情。 使用 iTextSharp,我们必须在页面上对角添加空心文本(作为一种水印)。 由于文本未知,我们猜测原始字体大小。 然后代码进入一个循环,它将测量渲染文本的大小,并向上或向下调整它,直到它的大小恰好适合填充页面而不剪切任何文本。 (所有这些猜测和测量都是使用 iTextSharp 完成的。)
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.)
我假设您正在使用
System.Drawing.Graphics
类上的MeasureString
方法。 您必须将PageUnit
属性设置为GraphicsUnit.Point
才能获取以点为单位的测量值。XSL-FO 很可能不会以与 GDI+ 相同的方式呈现。 特别是文本换行算法会有所不同。
但是,假设
PageUnit
是正确的,并且您有一个简单的布局,不涉及已换行的文本,那么您在估计 XSL-FO 生成的 PDF 的大小时可能会忽略一些明显的东西。 也许,您可以尝试将页面尺寸从 1 英寸更改为 9 英寸,间隔为 1 英寸。 然后,您可以使用标尺测量多余的空白,并尝试确定页面大小和多余空白之间的关系。 然后,您应该重新访问您的代码,找出您对文本大小的错误假设。I assume that you are using the method
MeasureString
method on theSystem.Drawing.Graphics
class. You have to set thePageUnit
property toGraphicsUnit.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.几年前我遇到了一个非常相似的问题。
我在自己的项目中发现,使用旧的 Win32 gdi 函数进行文本度量得到了更好的结果 (http://msdn.microsoft.com/en-us/library/dd144821(VS.85).aspx) 通过 P/Invoke。 它返回的结果与 GDI+ MeasureString 不同。 它们与 PDF 中看到的内容更加一致。
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.