【问题标题】:PDFSharp: Measuring height of long text with word wrapPDFSharp:使用自动换行测量长文本的高度
【发布时间】:2013-03-05 20:36:13
【问题描述】:

PDFSharp 支持在绘制长文本部分时自动换行:

textFormatter.DrawString(text, font, XBrushes.Black, new XRect(x, y, textAreaWidth, 1000), XStringFormats.TopLeft);

如果文本长于textAreaWidth,这将换行。

如何获取刚刚绘制的文字的高度?

我用gfx.MeasureString() 尝试过,但没有支持指定最大宽度的重载。 gfx.MeasureString() 返回不换行的文本大小。

感谢任何提示。

【问题讨论】:

  • 如果单页不够用,可能需要更多页,最好直接切换到 MigraDoc。如果您确定单页就足够了,只需向 XTextFormatter.DrawString 添加一个 out 参数,该参数返回刚刚绘制的文本的高度。

标签: c# pdf pdf-generation pdfsharp


【解决方案1】:

XTextFormatter 类(PDFsharp 附带的源代码)旨在帮助您入门。如果它不适合您的需要,请修改它。

由于 XTextFormatter 在内部保持 Y 位置,因此返回刚刚绘制的文本的高度将是一个相当简单的更改。

不要修改 XTextFormatter,而是考虑使用 MigraDoc Foundation(也包括在内)。

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      PdfSharp 的这个扩展并不适合我。不知道为什么,但我的身高一直比预期的要高(几乎是所需身高的两倍)。所以我决定为 XGraphics 对象编写一个扩展方法,我可以在其中指定一个 maxWidth 并在内部计算软换行符。 该代码使用默认的XGraphics.MeasureString(string, XFont) 到内联文本宽度并与文本中的单词聚合来计算换行符。 计算软换行符的代码如下所示:

      /// <summary>
      /// Calculate the number of soft line breaks
      /// </summary>
      private static int GetSplittedLineCount(this XGraphics gfx, string content, XFont font, double maxWidth)
      {
          //handy function for creating list of string
          Func<string, IList<string>> listFor = val => new List<string> { val };
          // string.IsNullOrEmpty is too long :p
          Func <string, bool> nOe = str => string.IsNullOrEmpty(str);
          // return a space for an empty string (sIe = Space if Empty)
          Func<string, string> sIe = str => nOe(str) ? " " : str;
          // check if we can fit a text in the maxWidth
          Func<string, string, bool> canFitText = (t1, t2) => gfx.MeasureString($"{(nOe(t1) ? "" : $"{t1} ")}{sIe(t2)}", font).Width <= maxWidth;
      
          Func<IList<string>, string, IList<string>> appendtoLast =
                  (list, val) => list.Take(list.Count - 1)
                                     .Concat(listFor($"{(nOe(list.Last()) ? "" : $"{list.Last()} ")}{sIe(val)}"))
                                     .ToList();
      
          var splitted = content.Split(' ');
      
          var lines = splitted.Aggregate(listFor(""),
                  (lfeed, next) => canFitText(lfeed.Last(), next) ? appendtoLast(lfeed, next) : lfeed.Concat(listFor(next)).ToList(),
                  list => list.Count());
      
          return lines;
      }
      

      完整代码参见以下要点:https://gist.github.com/erichillah/d198f4a1c9e8f7df0739b955b245512a

      【讨论】:

      • 谢谢,这对我有用,虽然我不完全理解代码。我对 C# 有点陌生,也许这就是原因。
      • 这样可以很好地返回行数,但是有没有办法确定每行的高度?
      • 伙计,你救了我的命..非常感谢,效果很好!更新:其他答案中推荐的 PrepareDrawString 听起来也很有希望
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 2016-01-02
      • 2021-12-04
      • 1970-01-01
      • 2019-01-14
      • 2013-03-08
      相关资源
      最近更新 更多