PDFSharp: Measuring height of long text with word wrap
Asked Answered
D

3

8

PDFSharp supports automatic text wrapping when drawing long text portions:

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

This will wrap the text if it is longer than textAreaWidth.

How can I get the height of the text that has just been drawn?

I tried it with gfx.MeasureString(), but there is no overload that supports specifying a maximal width. gfx.MeasureString() returns the size of the text without text wrapping.

Thanks for any hints.

Darrickdarrill answered 17/3, 2013 at 13:6 Comment(1)
If a single page is not enough and you may need more pages, then better switch to MigraDoc directly. If you are sure a single page will be enough for all times, just add an out parameter to XTextFormatter.DrawString that returns the height of the text that was just drawn.Whitsuntide
D
2

I found this extension of PdfSharp to be the answer to this problem:

http://developer.th-soft.com/developer/2015/07/17/pdfsharp-improving-the-xtextformatter-class-measuring-the-height-of-the-text/

You can clone or fork the relevant code here:

https://github.com/yolpsoftware/PdfSharp/tree/measure-text-height

Darrickdarrill answered 8/9, 2016 at 14:59 Comment(0)
A
10

This extension of PdfSharp didn't quite work for me. Don't know why but i was keeping getting a bigger height than expected (almost the double of the neededHeight). So I decided to write an extension method the the XGraphics object where i can specify a maxWidth and internally calculate the soft line breaks. The code uses the default XGraphics.MeasureString(string, XFont) to the inlined text Width and Aggregates with the words from the text to calclulate the Line breaks. The code to calculate the soft Line breaks looks like this :

/// <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;
}

See the following Gist for the complete code : https://gist.github.com/erichillah/d198f4a1c9e8f7df0739b955b245512a

Astrakhan answered 11/10, 2016 at 9:53 Comment(3)
Thanks, this worked for me, though I don't completely understand the code. I'm a bit new at C#, maybe that's why.Radmen
This works great to return the number of lines, but is there a way to determine the height of each line?Tieshatieup
Man, you saved my days..thanks a lot, works great! Update: PrepareDrawString as recommended in other answers also sounds promisingLorenza
W
4

The XTextFormatter class (source code included with PDFsharp) is meant to get you started. Modify it if it doesn't suit your needs.

Since XTextFormatter keeps the Y position internally, it would be a rather simple change to return the height of the text that was just drawn.

Instead of modifying XTextFormatter, consider using MigraDoc Foundation (also included) instead.

Whitsuntide answered 18/3, 2013 at 14:9 Comment(0)
D
2

I found this extension of PdfSharp to be the answer to this problem:

http://developer.th-soft.com/developer/2015/07/17/pdfsharp-improving-the-xtextformatter-class-measuring-the-height-of-the-text/

You can clone or fork the relevant code here:

https://github.com/yolpsoftware/PdfSharp/tree/measure-text-height

Darrickdarrill answered 8/9, 2016 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.