Calculate text height based on available width and font?

前端 未结 8 1471
醉酒成梦
醉酒成梦 2020-12-16 13:11

We are creating PDF documents on the fly from the database using PDFsharp.

I need to know the best way to calculate the height of the text area based on the font use

相关标签:
8条回答
  • 2020-12-16 13:57

    In .NET you can call Graphics.MeasureString to find out how large the drawn text is going to be.

    0 讨论(0)
  • 2020-12-16 13:58

    In .NET you can call Graphics.MeasureString to find out how large the drawn text is going to be.

    Right, but when using PDFsharp you call XGraphics.MeasureString.

    0 讨论(0)
  • 2020-12-16 14:01

    I had a similiar problem so I implemented this extension method:

    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;
    }
    
    0 讨论(0)
  • 2020-12-16 14:01

    The OP asked how to calculate text height based on available width and font. Windows .NET provides an API call for this which takes a width argument; the version of PDFsharp I'm using (0.9.653, .NET 1.1) does not.

    My solution - use the .NET API call with a Graphics object allocated for a custom-created Bitmap object to get the answer.

    What worked for me was to use a Bitmap that had 100 DPI resolution (critical) and happened to be the size of a Portrait page (probably less critical).

    Then I just asked .NET what the pixel size would be for painting on that bitmap.

    You probably will then want to convert the units from 1/100th of an inch to Points (for PDFsharp).

    ''' Adapted Code - this not tested or even compiled - Caveat Emptor!
    ''' Target: Visual Basic, .NET 1.1 (VS2003) [adapt as necessary]
    
    '  '  '  '  '  '  '  '  '  '  '  '  '  '  '  '
    '  GraphicsAlt.MeasureString() does substantially what System.Drawing MeasureString(...,Integer) does.
    '  '  '  '  '  '  '  '  '  '  '  '  '  '  '  '
    Public Module GraphicsAlt
    
        '
        ' Static data used Only to compute MeasureString() below.
        '
        '     Cache a single copy of these two objects, to address an otherwise unexplained intermittent exception.
        '
        Private Shared myImage As Bitmap = Nothing
        Private Shared myGraphics As Graphics = Nothing
    
        Public Shared Function GetMeasureGraphics() As Graphics
            If myImage Is Nothing Then
                myImage = New Bitmap(1700, 2200)  '' ... Specify 8.5x11 
                myImage.SetResolution(100, 100)   '' ... and 100 DPI (if you want different units, you might change this)
                myGraphics = Graphics.FromImage(myImage)
            End If
            Return myGraphics
        End Function
    
        'Given 1/100TH inch max width, return Rect to hold with units 1/100TH inch
        '
        Public Function MeasureString(ByVal text As String, ByVal aFont As System.Drawing.Font, ByVal width As Integer) As System.Drawing.SizeF
            Return (GraphicsAlt.GetMeasureGraphics()).MeasureString(text, aFont, width)
        End Function
    
    End Module
    
    0 讨论(0)
  • 2020-12-16 14:03

    PDFsharp includes a class XTextFormatter that can be used to draw text with linebreaks.

    However it can not determine the height needed for the text. Inspired by a comment from @Wakka02 I improved this class, generating class XTextFormatterEx.
    In my opinion it also answers the original question, therefore I post an answer.
    I know this is an old question and the answer may not help the OP, but it is a frequently asked question and the answer may help others.

    The new class has 500 lines of code - and I think this would be too much for this post.

    The source code can be found on the PDFsharp forum:
    http://forum.pdfsharp.net/viewtopic.php?p=9213#p9213

    It can also be found in my humble blog:
    http://developer.th-soft.com/developer/pdfsharp-improving-the-xtextformatter-class-measuring-the-height-of-the-text/

    When using the new class, you can first call PrepareDrawString to find out how much of the text fits and which height the fitting text has. Then your decoder can draw the prepared text or prepare another text or prepare the same text with a different rectangle.

    My new class at work: XTextFormatterEx tf = new XTextFormatterEx(gfx); int lastCharIndex; double neededHeight;

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

    Preparing the text invokes MeasureString many times. Later the prepared text can be drawn without invoking MeasureString again.

    As of today (Juli 17, 2015) the class XTextFormatterEx (like the original XTextFormatter) uses internal fields of the XFont class. This requires special treatment when compiling the class. I decided to copy my XTextFormatterEx class into the PDFsharp folder after downloading the complete source package for PDFsharp 1.32.
    Anybody trying to modify either the XTextFormatter or XTextFormatterEx class will face the same problem.
    I hope this issue will be solved with future versions of PDFsharp, allowing modified versions of these classes to be included in the application project.

    0 讨论(0)
  • 2020-12-16 14:07

    I wrote a small extension method to the XGraphic object to do just that : Calclulate the exact text height (and width) by specifiying the maxWidth. See the following gist for the code : https://gist.github.com/erichillah/d198f4a1c9e8f7df0739b955b245512a

    0 讨论(0)
提交回复
热议问题