Вычисление значения emSize для шрифта, чтобы текст заполнил область

Я уже целую вечность рву на себе волосы, поэтому подумал, что попытаюсь получить некоторую помощь ... Я работаю с PDFsharp (может быть или не быть значительным) и пытаюсь поставить водяной знак в pdf document, когда он загружается через мое веб-приложение asp.net.

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

Предполагая, что я использую Arial и полужирный шрифт и могу найти ширину страницы в см/мм/дюймах/pt, как мне рассчитать emSize шрифта, необходимый для того, чтобы любой введенный текст увеличивался/сокращался, чтобы заполнить ширину?

Конструктор PDFsharp XFont принимает имя шрифта и emSize.

Редактировать: Большое спасибо за предложения, ребята, вот что я реализовал в конце:

    PdfDocument doc = PdfReader.Open(stream, PdfDocumentOpenMode.Modify);

    foreach (PdfPage page in doc.Pages)
    {
        double watermarkWidth = (Math.Sqrt(Math.Pow(page.Height.Point, 2) + Math.Pow(page.Width.Point, 2)));
        //reduce by 10% so that the wording doesn't go right into the corners
        watermarkWidth -= (watermarkWidth / 10);

        XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);

        double emSize = 150;
        XFont font = new XFont("Arial", emSize, XFontStyle.Bold);
        XSize size = gfx.MeasureString(watermark, font);

        while (size.Width > watermarkWidth && emSize > 10)
        {
            emSize -= 5;
            font = new XFont("Arial", emSize, XFontStyle.Bold);
            size = gfx.MeasureString(watermark, font);
        }

        gfx.TranslateTransform(page.Width / 2, page.Height / 2);
        gfx.RotateTransform(-Math.Atan(page.Height / page.Width) * 180 / Math.PI);
        gfx.TranslateTransform(-page.Width / 2, -page.Height / 2);

        XGraphicsPath path = new XGraphicsPath();

        path.AddString(watermark, font.FontFamily, XFontStyle.Bold, emSize,
            new XPoint((page.Width - size.Width) / 2, (page.Height - size.Height) / 2),
            XStringFormats.Default);

        XPen pen = new XPen(XColor.FromArgb(75, 255, 0, 0), 2);

        gfx.DrawPath(pen, path);
    }
    doc.Save(stream, false);

person RazorUK84    schedule 30.07.2013    source источник


Ответы (2)


Ограничена ли длина водяного знака (в символах)? Если это так, вы можете взять допустимое количество символов и вычислить ширину строк, таких как "@@@...", "WWW..." и "МММ..." в цикле с уменьшением размера шрифта, пока он не подойдет .
Тогда у вас будет единый размер шрифта, который можно использовать для всех текстов.

Водяной знак тогда будет меньше - если рассчитать ширину на 30 "@" и пользователь просто введет "Совершенно секретно"...

Лучший метод: позвольте пользователю ввести водяной знак, затем используйте цикл с уменьшением размера шрифта, пока нужный текст не впишется в доступное пространство.

person I liked the old Stack Overflow    schedule 30.07.2013
comment
Я в процессе реализации вашего предложения (второго). Большое спасибо - person RazorUK84; 30.07.2013

Может быть, таким образом (я не знаю, как именно работает PDFsharp, но в обычных формах или Wpf этот код предоставит максимально возможный шрифт)

public Font GetFont(Panel Wathermark, string textToPaint)
        {
                Font result = new Font("Bold", 1);
                using (Graphics measure = Wathermark.CreateGraphics())
                {
                    SizeF tempSize;
                    tempSize = measure.MeasureString(textToPaint, result);

                    while (tempSize.Width < Wathermark.Width && tempSize.Height < Wathermark.Height)
                    {
                        tempSize = measure.MeasureString(textToPrint, result);
                        var tempSizeToIncrease = result.Size; //writeprotected
                        result = new Font(result.Name, tempSizeToIncrease += 0.1f);
                    }
                }
                return result;
            }
person BudBrot    schedule 30.07.2013
comment
Спасибо за предложение и код pengu. Единственная причина, по которой я отметил другой ответ как ответ, заключается в том, что они были первыми. Но вы оба дали очень похожие ответы, так что спасибо. - person RazorUK84; 30.07.2013