Рассчитать высоту текста на основе доступной ширины и шрифта? - PullRequest
16 голосов
/ 23 мая 2009

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

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

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

Ответы [ 8 ]

20 голосов
/ 24 августа 2009

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

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

10 голосов
/ 25 августа 2009

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

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

6 голосов
/ 03 апреля 2014

У меня была похожая проблема, поэтому я реализовал этот метод расширения:

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 голосов
/ 24 мая 2009

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

1 голос
/ 11 октября 2016

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

0 голосов
/ 17 июля 2015

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

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

Новый класс имеет 500 строк кода - и я думаю, что это будет слишком много для этого поста.

Исходный код можно найти на форуме PDFsharp:
http://forum.pdfsharp.net/viewtopic.php?p=9213#p9213

Это также можно найти в моем скромном блоге:
http://developer.th -soft.com / разработчик / PDFsharp улучшающие-на-xtextformatter-класса измерительно-на-высоты-оф-текст /

При использовании нового класса вы можете сначала позвонить PrepareDrawString, чтобы узнать, сколько текста умещается и какую высоту имеет соответствующий текст. Затем ваш декодер может нарисовать подготовленный текст или подготовить другой текст или подготовить тот же текст с другим прямоугольником.

Мой новый класс на работе: XTextFormatterEx tf = new XTextFormatterEx (gfx); int lastCharIndex; double requiredHeight;

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

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

0 голосов
/ 18 июня 2015

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

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 () будет напечатан предоставленный текст, а затем будет возвращена высота напечатанного текста.

0 голосов
/ 07 марта 2013

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

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

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

Тогда я просто спросил .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
...