using System; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Printing; using System.Runtime.InteropServices; namespace Elwig.Helpers.Printing { public class PdfPrintDocument : PrintDocument { private readonly IntPtr _handle; private readonly int _pageCount; private readonly double _dpi; private int _currentPage; public PdfPrintDocument(string path, string? password = null, double dpi = 300.0) : base() { _handle = PdfiumNative.FPDF_LoadDocument(path, password); _pageCount = PdfiumNative.FPDF_GetPageCount(_handle); _dpi = dpi; } protected override void Dispose(bool disposing) { PdfiumNative.FPDF_CloseDocument(_handle); base.Dispose(disposing); } protected override void OnBeginPrint(PrintEventArgs evt) { _currentPage = (PrinterSettings.FromPage != 0) ? (PrinterSettings.FromPage - 1) : 0; base.OnBeginPrint(evt); } protected override void OnPrintPage(PrintPageEventArgs evt) { if (_currentPage < _pageCount) { IntPtr page = PdfiumNative.FPDF_LoadPage(_handle, _currentPage); double width = PdfiumNative.FPDF_GetPageWidth(page); double height = PdfiumNative.FPDF_GetPageHeight(page); int pixelWidth = (int)(width / 72.0 * _dpi); int pixelHeight = (int)(height / 72.0 * _dpi); IntPtr bitmap = PdfiumNative.FPDFBitmap_Create(pixelWidth, pixelHeight, 1); PdfiumNative.FPDF_RenderPageBitmap(bitmap, page, 0, 0, pixelWidth, pixelHeight, 0, 0); IntPtr buffer = PdfiumNative.FPDFBitmap_GetBuffer(bitmap); int stride = PdfiumNative.FPDFBitmap_GetStride(bitmap); using (var bmp = new Bitmap(pixelWidth, pixelHeight, stride, PixelFormat.Format32bppArgb, buffer)) { evt.Graphics?.DrawImage(bmp, evt.PageBounds); } _currentPage++; PdfiumNative.FPDFBitmap_Destroy(bitmap); PdfiumNative.FPDF_ClosePage(page); } evt.HasMorePages = _currentPage < ((PrinterSettings.ToPage == 0) ? _pageCount : Math.Min(PrinterSettings.ToPage, _pageCount)); base.OnPrintPage(evt); } } internal partial class PdfiumNative { [LibraryImport("pdfium.dll")] public static partial void FPDF_InitLibrary(); [LibraryImport("pdfium.dll")] public static partial void FPDF_DestroyLibrary(); [LibraryImport("pdfium.dll", StringMarshalling = StringMarshalling.Utf8)] public static partial IntPtr FPDF_LoadDocument(string filePath, string? password); [LibraryImport("pdfium.dll")] public static partial void FPDF_CloseDocument(IntPtr document); [LibraryImport("pdfium.dll")] public static partial int FPDF_GetPageCount(IntPtr document); [LibraryImport("pdfium.dll")] public static partial IntPtr FPDF_LoadPage(IntPtr document, int pageIndex); [LibraryImport("pdfium.dll")] public static partial void FPDF_ClosePage(IntPtr page); [LibraryImport("pdfium.dll")] public static partial double FPDF_GetPageWidth(IntPtr page); [LibraryImport("pdfium.dll")] public static partial double FPDF_GetPageHeight(IntPtr page); [LibraryImport("pdfium.dll")] public static partial IntPtr FPDFBitmap_Create(int width, int height, int alpha); [LibraryImport("pdfium.dll")] public static partial void FPDFBitmap_Destroy(IntPtr bitmap); [LibraryImport("pdfium.dll")] public static partial IntPtr FPDFBitmap_GetBuffer(IntPtr bitmap); [LibraryImport("pdfium.dll")] public static partial int FPDFBitmap_GetStride(IntPtr bitmap); [LibraryImport("pdfium.dll")] public static partial void FPDF_RenderPageBitmap(IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags); } }