Pdfium stretches or squashes document on printing

1.1k views Asked by At

I'm using PdfiumViewer in one of my C# applications. This is the part of the code which I'm using for printing:

public documentCopies = 2; // here for example's sake, in the app it's set in another part of the code

private void Completed(string newDocName)
{
    short numCopies = 1;

    if (documentCopies > 0)
    {
        numCopies = Convert.ToInt16(documentCopies);
    }

    var path = localDocLocation + "\\" + newDocName;
    string extension = GetExtension(newDocName).ToLower();

    if (extension == "pdf")
    {
        using (var document = PdfiumViewer.PdfDocument.Load(path))
        {
            using (var printDocument = document.CreatePrintDocument())
            {
                // check the current default printer
                System.Drawing.Printing.PrinterSettings settings = new System.Drawing.Printing.PrinterSettings();
                string defaultPrinterName = settings.PrinterName;

                printDocument.OriginAtMargins = true;
                printDocument.PrinterSettings.PrintFileName = newDocName;
                printDocument.PrinterSettings.Copies = numCopies;
                printDocument.PrintController = new System.Drawing.Printing.StandardPrintController();
                printDocument.PrinterSettings.PrinterName = printerName;

                try
                {
                    printDocument.Print();
                } catch (Exception pex)
                {
                    MessageBox.Show(pex.Message.ToString()));

                    printDocument.PrinterSettings.PrinterName = defaultPrinterName;

                    try
                    {
                        printDocument.Print();
                    } catch(Exception pex2)
                    {
                        MessageBox.Show(pex2.Message.ToString());
                    }
                }
            }
        }
    }
    else
    {
        // do smth else
    }
}

PDF documents which are printed are in a format fit for a thermal printer (80mm width), and are created outside of my application, but with that width in mind.

If I print them from, say Adobe Acrobat or Foxit Reader (directly or via CLI), or any other PDF viewer, the print is identical to what I see when viewing the document in the appropriate viewer. You can see the differences in the following image.

enter image description here

I've tried simplifying the code, and turning it into this, just for testing, but the end results were the same - stretched document in printing.

private void Completed(string newDocName)
{
    var path = localDocLocation + "\\" + newDocName;

    using (var document = PdfiumViewer.PdfDocument.Load(path))
    {
        using (var printDocument = document.CreatePrintDocument())
        {
            printDocument.PrintController = new System.Drawing.Printing.StandardPrintController();
            printDocument.Print();
        }
    }
}

Trying to force shrinking to margin (document.CreatePrintDocument(PdfiumViewer.PdfPrintMode.ShrinkToMargin)), as suggested in this SO answer did not work - the printout was still distorted. Also, if there's more content than in this specific case, the printed content is squashed. The printout's height is just a little bit larger than the document I mentioned in my question.

I'm guessing that I'm doing something wrong, but I don't know what. Should I set the page height to some value? Should I unset it, and let it fallback to whatever the default value is? If so, how should I do that?

1

There are 1 answers

1
FiddlingAway On BEST ANSWER

I've managed to solve this in the following manner (though I'm not sure if it's the best way to do it).

First, I wanted to check the properties / contents of the variables document and printDocument (see my question to understand how they were initialized). I achieved this by doing:

    string tempConvert = JsonConvert.SerializeObject(document);
    dynamic docProperties = JsonConvert.DeserializeObject(tempConvert);

    MessageBox.Show(docProperties.ToString());

    string tmpProp = "";
    foreach (var iProp in printDocument.GetType().GetProperties())
    {
        tmpProp += iProp.Name + ":" + iProp.GetValue(printDocument, null) + "\r\n";
    }

    MessageBox.Show(tmpProp.Trim());

The first one - document - held info on the dimensions of the document I wanted to print, while printDocument held various info regarding the current printer settings (paper orientation, margins, paper size, etc).

My next step was to extract the document dimensions from the docProperties variable, and I did this like this:

    string[] docDimensions = docProperties.PageSizes[0].ToString().Split(' ');
    char[] toTrim = { ' ', ',' };
    int docWidth = Convert.ToInt32(FormatNumber(docDimensions[0].Trim(toTrim)));
    int docHeight = Convert.ToInt32(FormatNumber(docDimensions[1].Trim(toTrim))) + 1;

Finally, I used the docWidth and docHeight to change the paper size, so that it would suit my needs (thermal POS printer, 80mm roll paper width):

    printDocument.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("customsize", Convert.ToInt32(1.4 * docWidth), Convert.ToInt32(1.4 * docHeight));

That 1.4 bit was something I settled on after a couple of series of trial and error.

Again, I'm aware that this is most likely not the best way to resolve the issue universally, but it did solve this specific problem.