Question

I have been pulling my hair out on this one for ages now, so thought I'd try to get some help... I'm working with PDFsharp (may or may not be significant) and trying to put a watermark into a pdf document when it gets downloaded via my asp.net web app.

My problem comes with that the user needs to be able to define the text in the watermark, so I can't use a fixed text size, also, the pdf page size can change.

Assuming that I'm using Arial and bold, and can find the page width in cm/mm/inch/pt, how do I calculate the font's emSize that is needed so that whatever text is entered grows/shrinks to fill the width?

The PDFsharp XFont constructor takes font name and emSize.

Edit: Many thanks for the suggestions guys, this is what I implemented in the end:

    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);
Was it helpful?

Solution

Is the length of the watermark (in characters) limited? If so, you can take the allowed number of characters and calculate the width of strings like "@@@...", "WWW..." and "MMM..." in a loop with decreasing font sizes until it fits.
Then you will have a single font size that can be used for all texts.

The watermark will then be smaller - if you calculate the width for 30 "@" and the user just enters "Top Secret" ...

Better method: let the user enter the watermark, then use a loop with decreasing font sizes until the desired text fits into the available space.

OTHER TIPS

Maybe this way (i dont know how PDFsharp works exactly, but in a normal Forms or Wpf this code would deliver the biggest possible Font)

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;
            }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top