简体   繁体   中英

PDF printing in .NET Core using System.Drawing.Printing

I'm printing PDF files by converting every page to PNG image with PDFiumSharp. Next, I draw this image to Graphics.

private void PrintPage(object sender, PrintPageEventArgs ev)
{
    ev.Graphics.DrawImage(images[pageNum], ev.Graphics.VisibleClipBounds);
    pageNum++;
    if (pageNum == images.Count)
    {
        ev.HasMorePages = false;
    }
    else
    {
        ev.HasMorePages = true;
    }
}

public void Print()
{
    printDocument.PrintPage += new PrintPageEventHandler(PrintPage);
    pageNum = 0;

    if (printDocument.PrinterSettings.IsValid)
    {
        printDocument.Print();
    }
    else
    {
        throw new Exception("Printer is invalid.");
    }
}

The problem is that printer receives very large data and the whole process works slowly. I tried to use lpr command on Windows. It works directly with PDF files, but my application is required to support duplex, different paper source, etc. which is unavailable in lpr .

How can I print PDF using System.Drawing.Printig (or something other what offers similar functionalities) without conversion to image? I use .NET Core 3.1, my application should be cross-platform.

Actually, you need to choose any 2 of 3:

  1. Send data to printer directly without raster images
  2. Use System.Drawing.Printing
  3. Cross-platform

For example, 1 and 2 work fine on Windows. There are cross-platform PDF libraries that can parse and print PDF directly to System.Drawing.Graphics. Look at this sample .

The problem is that System.Drawing does not work well on Linux and macOS. It uses libgdiplus and this implementation has many practical issues.
For example, libgdiplus does not handle clipping paths well enough. I fixed few related issues there ( #545 , #547 , #552 ) and found serious blockers for further improvements.

The first one is maintainers. They did not respond to questions and reviewed simple pull requests by months. It looks that Microsoft is not very interested in this project.

The second blocker is internal architecture. There are 2 old implementations of regions (based on bitmaps and rectangles) that should be reconsidered. However, without communication with maintainers it is also infeasible to make architectural changes.

I think you have 2 options:

  1. Use PDF library that can print to System.Drawing.Graphics without intermediate images (like the sample above). It will work fine on Windows. On Linux, you will need either:

    • fix found issues in libgdiplus yourself, use customized version in your production.
    • render PDF to images and then print raster images.
  2. Do not use System.Drawing.Printing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM