Подтвердить что ты не робот

Вычислить высоту текста на основе доступной ширины и шрифта?

Мы создаем PDF-документы "на лету" из базы данных, используя PDFsharp.

Мне нужно знать, как лучше всего вычислить высоту текстовой области на используемом шрифте и доступной ширине.

Мне нужно знать высоту, чтобы я мог обрабатывать разрывы страниц, когда это необходимо.

4b9b3361

Ответ 1

В .NET вы можете позвонить Graphics.MeasureString, чтобы узнать, как большой нарисованный текст будет.

Правильно, но при использовании PDFsharp вы вызываете XGraphics.MeasureString.

Ответ 2

Объект 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));

Это поможет вам. Пожалуйста, подумайте, что я не тестировал этот код, поскольку я написал его на лету, чтобы помочь. Он может содержать некоторые ошибки времени компиляции, но вы можете получить эту идею.

Ответ 3

В .NET вы можете вызвать Graphics.MeasureString, чтобы узнать, насколько большой будет рисованный текст.

Ответ 4

У меня была аналогичная проблема, поэтому я применил этот метод расширения:

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

Ответ 5

Я написал небольшой метод расширения для объекта XGraphic, чтобы сделать именно это: Calclulate точная высота текста (и ширина), указав maxWidth. См. Следующий код для кода: https://gist.github.com/erichillah/d198f4a1c9e8f7df0739b955b245512a

Ответ 6

ОП спросил, как рассчитать высоту текста на основе доступной ширины и шрифта. Windows.NET предоставляет вызов API для этого, который принимает аргумент ширины; версия PDFsharp, которую я использую (0.9.653,.NET 1.1), не работает.

Мое решение - используйте вызов .NET API с объектом Graphics, выделенным для созданного пользователем объекта Bitmap, чтобы получить ответ.

Что сработало для меня, было использование растрового изображения с разрешением 100 DPI (критическое) и оказалось размером с портретную страницу (возможно, менее критичной).

Затем я просто спросил .NET, какой размер пикселя будет для рисования на этом растровом изображении.

Вероятно, вы захотите преобразовать единицы измерения с 1/100-й дюйма в точки (для 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

Ответ 7

Если кто-то все еще хочет найти ответ, я применил разумно простой способ узнать высоту полученного текста.

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

Объяснение кода:

Сначала напечатайте текст. Я включил опциональный XTextFormatter, называемый tf, потому что я использую XGraphics или XTextFormatters взаимозаменяемо в своем приложении.

Затем вычислите, как долго текст был получен с помощью MeasureString(). Ширина.

Затем вычислите, сколько строк текста было. Это делается путем деления общей длины найденного ранее текста на ширину предоставленного прямоугольника (поле), где печатается налог. Я сделал это с циклом while здесь.

Умножьте высоту текста (используя graph.MeasureString(). Height) на количество строк. Это конечная высота вашего текста.

Вернуть значение высоты. Теперь вызов функции PrintString() будет распечатывать текст, предоставленный после возвращения высоты печатного текста.

Ответ 8

PDFsharp включает класс XTextFormatter, который можно использовать для рисования текста с помощью строк.

Однако он не может определить высоту, необходимую для текста. Вдохновленный комментарием от @Wakka02, я улучшил этот класс, создав класс XTextFormatterEx.
По-моему, это также отвечает на исходный вопрос, поэтому я отправляю ответ. Я знаю, что это старый вопрос, и ответ может не помочь ОП, но это часто задаваемый вопрос, и ответ может помочь другим.

Новый класс имеет 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 = новый XTextFormatterEx (gfx);   int lastCharIndex;   double needHeight;

// 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.

На сегодняшний день (Juli 17, 2015) класс XTextFormatterEx (как и исходный XTextFormatter) использует внутренние поля класса XFont. Это требует специального лечения при компиляции класса. Я решил скопировать мой класс XTextFormatterEx в папку PDFsharp после загрузки полного исходного пакета для PDFsharp 1.32.
Любой, кто пытается изменить класс XTextFormatter или XTextFormatterEx, столкнутся с той же проблемой.
Я надеюсь, что эта проблема будет решена с будущими версиями PDFsharp, позволяя включить в проект приложения модифицированные версии этих классов.