我们正在使用PDFsharp从数据库中即时创建 PDF 文档。
我需要知道根据使用的字体和可用宽度计算文本区域高度的最佳方法。
我需要知道高度,以便在需要时处理分页符。
PdfSharp.Drawing.XGraphics 对象有一个 MeasureString 方法,可以返回您需要的内容。
var pdfDoc = new PdfSharp.Pdf.PdfDocument();
var pdfPage = pdfDoc.AddPage();
var pdfGfx = PdfSharp.Drawing.XGraphics.FromPdfPage(pdfPage);
var pdfFont = new PdfSharp.Drawing.XFont("Helvetica", 20);
while (pdfGfx.MeasureString("Hello World!").Width > pdfPage.Width)
--pdfFont.Size;
pdfGfx.DrawString("Hello World!", pdfFont
, PdfSharp.Drawing.XBrushes.Black
, new PdfSharp.Drawing.XPoint(100, 100));
这应该可以帮助你。请考虑到我没有测试这段代码,因为我是为了提供帮助而即时编写的。它可能包含一些编译时错误,但您可能会明白。
在 .NET 中,您可以调用 Graphics.MeasureString 来确定绘制文本的大小。
对,但是当使用 PDFsharp 时,您调用 XGraphics.MeasureString。
我有一个类似的问题,所以我实现了这个扩展方法:
public static double MeasureHeight(this PdfSharp.Drawing.XGraphics gfx, string text, PdfSharp.Drawing.XFont font, int width)
{
var lines = text.Split('\n');
double totalHeight = 0;
foreach (string line in lines)
{
var size = gfx.MeasureString(line, font);
double height = size.Height + (size.Height * Math.Floor(size.Width / width));
totalHeight += height;
}
return totalHeight;
}
在 .NET 中,您可以调用Graphics.MeasureString来确定绘制文本的大小。
我为 XGraphic 对象编写了一个小的扩展方法来做到这一点:通过指定 maxWidth 来计算确切的文本高度(和宽度)。有关代码,请参阅以下要点:https ://gist.github.com/erichillah/d198f4a1c9e8f7df0739b955b245512a
OP询问如何根据可用宽度和字体计算文本高度。Windows .NET 为此提供了一个 API 调用,它接受一个宽度参数;我正在使用的 PDFsharp 版本(0.9.653,.NET 1.1)没有。
我的解决方案 - 使用 .NET API 调用和为自定义创建的 Bitmap 对象分配的 Graphics 对象来获得答案。
对我有用的是使用具有 100 DPI 分辨率(关键)并且恰好是肖像页面大小(可能不太关键)的位图。
然后我只是问.NET 在该位图上绘制的像素大小是多少。
然后,您可能希望将单位从 1/100 英寸转换为点(对于 PDFsharp)。
''' 改编代码 - 这未经测试甚至编译 - 警告 Emptor! ''' 目标:Visual Basic、.NET 1.1 (VS2003) [根据需要调整] ''''''''''''''''''' ' GraphicsAlt.MeasureString() 的作用与 System.Drawing MeasureString(...,Integer) 的作用基本相同。 ''''''''''''''''''' 公共模块 GraphicsAlt ' ' 静态数据仅用于计算下面的 MeasureString()。 ' ' 缓存这两个对象的单个副本,以解决其他无法解释的间歇性异常。 ' 私人共享 myImage 作为位图 = 无 私人共享 myGraphics 作为图形 = 没有 公共共享函数 GetMeasureGraphics() 作为图形 如果 myImage 什么都不是,那么 myImage = New Bitmap(1700, 2200) '' ... 指定 8.5x11 myImage.SetResolution(100, 100) '' ... 和 100 DPI(如果你想要不同的单位,你可以改变这个) myGraphics = Graphics.FromImage(myImage) 万一 返回我的图形 结束功能 '给定 1/100TH 英寸最大宽度,返回 Rect 以保持单位 1/100TH 英寸 ' 公共函数 MeasureString(ByVal text As String, ByVal aFont As System.Drawing.Font, ByVal width As Integer) As System.Drawing.SizeF 返回 (GraphicsAlt.GetMeasureGraphics()).MeasureString(text, aFont, width) 结束功能 端模块
如果有人仍然想找到答案,我已经实现了一个相当容易理解的方法来找出结果文本的高度。
Public Function PrintString(text As String, ft As XFont, rect As XRect, graph As XGraphics, b As SolidBrush, Optional tf As XTextFormatter = Nothing) As Integer
If Not IsNothing(tf) Then
tf.DrawString(text, ft, b, rect)
Else
Dim drawLeft As New XStringFormat
drawLeft.Alignment = XStringAlignment.Near
graph.DrawString(text, ft, b, rect, drawLeft)
End If
Dim width As Double = graph.MeasureString(text, ft).Width
Dim multiplier As Integer = 0
While width > 0
multiplier += 1
width -= rect.Width
End While
Dim height As Double = (graph.MeasureString(text, ft).Height) * multiplier
Return height
End Function
解释代码:
首先,打印文本。我包含了一个名为 tf 的可选 XTextFormatter,因为我在我的应用程序中可以互换使用 XGraphics 或 XTextFormatters。
然后,通过 MeasureString().Width 计算文本的长度。
然后,计算有多少行文本。这是通过将之前找到的文本的总长度除以提供的打印税款的矩形(框)的宽度来完成的。我在这里使用了一个while循环。
将文本的高度(使用 graph.MeasureString().Height)乘以行数。这是文本的最终高度。
返回高度值。现在,调用 PrintString() 函数将打印提供的文本,然后返回打印文本的高度。
PDFsharp 包含一个类 XTextFormatter,可用于绘制带有换行符的文本。
但是它无法确定文本所需的高度。受@Wakka02 评论的启发,我改进了这个类,生成了 XTextFormatterEx 类。
我认为它也回答了原始问题,因此我发布了答案。
我知道这是一个老问题,答案可能对 OP 没有帮助,但这是一个常见问题,答案可能对其他人有帮助。
新类有 500 行代码——我认为这对于这篇文章来说太多了。
源代码可以在 PDFsharp 论坛上找到:http:
//forum.pdfsharp.net/viewtopic.php?p =9213#p9213
它也可以在我不起眼的博客中找到:http:
//developer.th-soft.com/developer/pdfsharp-improving-the-xtextformatter-class-measuring-the-height-of-the-text/
使用新类时,您可以先调用PrepareDrawString
以了解文本适合多少以及适合文本的高度。然后您的解码器可以绘制准备好的文本或准备另一个文本或准备具有不同矩形的相同文本。
我的新课程:XTextFormatterEx tf = new XTextFormatterEx(gfx); int lastCharIndex; 双倍需要高度;
// Draw the text in a box with the optimal height
// (magic: we know that one page is enough).
XRect rect = new XRect(40, 100, 250, double.MaxValue);
//tf.Alignment = ParagraphAlignment.Left;
tf.PrepareDrawString(text, font, rect,
out lastCharIndex, out neededHeight);
rect = new XRect(40, 100, 250, neededHeight);
gfx.DrawRectangle(XBrushes.SeaShell, rect);
// Both variants should look the same.
// Optimized version: draw the prepared string.
tf.DrawString(XBrushes.Black, XStringFormats.TopLeft);
准备文本会多次调用 MeasureString。稍后无需再次调用 MeasureString 即可绘制准备好的文本。
截至今天(2015 年 7 月 17 日),XTextFormatterEx 类(与原来的 XTextFormatter 一样)使用 XFont 类的内部字段。这需要在编译类时进行特殊处理。在下载了 PDFsharp 1.32 的完整源包后,我决定将我的 XTextFormatterEx 类复制到 PDFsharp 文件夹中。
任何试图修改 XTextFormatter 或 XTextFormatterEx 类的人都将面临同样的问题。
我希望这个问题将在 PDFsharp 的未来版本中得到解决,允许将这些类的修改版本包含在应用程序项目中。