PDFsharp & MigraDoc Foundation

Page 1 of 1

Author:  antony_scott [ Tue Jul 23, 2013 10:04 am ]
Post subject:  XTextFormatter.MeasureString


I've been using PDFSharp recently and needed to pull in some dynamic text and add it to the end of an existing PDF. The problem I had was knowing how much height the last piece of text used. I'm using XTextFormatter.DrawString and making it word wrap by providing plenty of height for it to work with.

    var rect = new XRect(textMargin, y, page.Width - (textMargin * 2), page.Height - y);
    textFormatter.DrawString(partText, font, XBrushes.Black, rect, XStringFormats.TopLeft);

As you can see I am giving DrawString the rest of the page to work with.

I've come up with a nasty little hack to work out the height the most recent DrawString used by writing a wrapper around XTextFormatter with a bit of reflection code to get at the private List<Block> blocks field

        public XSize GetDrawingSize()
            var blocks = GetType()
                .GetField("blocks", BindingFlags.Instance | BindingFlags.NonPublic)
                .GetValue(this) as IList;

            double x = 0.0, y = 0.0;
            if (blocks != null)
                foreach (var block in blocks)
                    var location =
                        (XPoint) block
                                     .GetField("Location", BindingFlags.Instance | BindingFlags.Public)

                    var width =
                        (double) block
                                     .GetField("Width", BindingFlags.Instance | BindingFlags.Public)

                    x = Math.Max(x, location.X + width);
                    y = Math.Max(y, location.Y);
            return new XSize(x, y + GetFontLineHeight());

I've had to use a foreach loop rather than Linq because the Block class is private to the XTextFormatter class.

Here is the code for GetFontLineHeight ...

        protected double GetFontLineHeight()
            var font = GetType()
                .GetField("font", BindingFlags.Instance | BindingFlags.NonPublic)
                .GetValue(this) as XFont;

            return font.GetHeight(_gfx);

It's very hackety hacky, but it does work.

What I'd like to do is provide a fix to PDFSharp, probably in the form of a MeasureString method within the XTextFormatter class. I think I'd just refactor DrawString and MeasureString to use the same block/layout code, the difference being whether or not to Draw the string.

So, my question is - How do I contribute code to PDFSharp?

Author:  antony_scott [ Tue Jul 23, 2013 4:13 pm ]
Post subject:  Re: XTextFormatter.MeasureString

I got the svn repository onto my PC and noticed this at the top of XTextFormatter ...

  /// <summary>
  /// Represents a very simple text formatter.
  /// If this class does not satisfy your needs on formatting paragraphs I recommend to take a look
  /// at MigraDoc Foundation. Alternatively you should copy this class in your own source code and modify it.
  /// </summary>

Alternatively you should copy this class in your own source code and modify it.

So, that's what I've done. I've created my own TextFormatter which simply returns the size of the text it rendered in DrawString. Inside the loop which draws the strings I have this ...

    width = Math.Max(width, block.Location.X + block.Width);
    height = Math.Max(height, block.Location.Y + _lineHeight);

... and I return the size like so ...

return new XSize(width, height);

It works a treat :D

Author:  eric_burcham [ Mon Jun 02, 2014 4:41 pm ]
Post subject:  Re: XTextFormatter.MeasureString

antony_scott wrote:
I got the svn repository onto my PC and noticed this at the top of XTextFormatter ...

So where did you find an SVN repository you could connect to? On the listed sites at Codeplex and SoureForge, I'm only finding a .zip download for the source code. I'd rather pull the SVN repo and submit patches if I fix something / add a feature.



Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group