diff --git a/Elwig/Elwig.csproj b/Elwig/Elwig.csproj index 7d2919b..cf6c5f5 100644 --- a/Elwig/Elwig.csproj +++ b/Elwig/Elwig.csproj @@ -3,6 +3,7 @@ WinExe net10.0-windows + x64 enable true true @@ -22,6 +23,7 @@ + @@ -31,15 +33,12 @@ - - - diff --git a/Elwig/Helpers/Printing/Pdf.cs b/Elwig/Helpers/Printing/Pdf.cs index d8091fb..cd253be 100644 --- a/Elwig/Helpers/Printing/Pdf.cs +++ b/Elwig/Helpers/Printing/Pdf.cs @@ -1,5 +1,4 @@ using Elwig.Windows; -using PdfiumViewer; using System; using System.Collections.Generic; using System.Diagnostics; @@ -27,6 +26,7 @@ namespace Elwig.Helpers.Printing { public static bool IsReady => WinziPrintProc != null; public static async Task Init(Action? evtHandler = null) { + PdfiumNative.FPDF_InitLibrary(); // NOTE: If the WinziPrint daemon is already running this will succeed, but the process will fail. // Should be no problem, as long as the daemon is not closed var p = new Process() { StartInfo = new() { @@ -47,6 +47,7 @@ namespace Elwig.Helpers.Printing { public static Task Cleanup() { WinziPrintProc?.Kill(true); WinziPrintProc?.Close(); + PdfiumNative.FPDF_DestroyLibrary(); return Task.CompletedTask; } @@ -123,9 +124,9 @@ namespace Elwig.Helpers.Printing { public static Task Print(string path, PrinterSettings settings) { try { - using var doc = PdfDocument.Load(path); - using var printDoc = doc.CreatePrintDocument(PdfPrintMode.CutMargin); - printDoc.PrinterSettings = settings; + using var printDoc = new PdfPrintDocument(path) { + PrinterSettings = settings, + }; printDoc.Print(); } catch (Exception e) { MessageBox.Show("Beim Drucken ist ein Fehler aufgetreten:\n\n" + e.Message, "Fehler beim Drucken", MessageBoxButton.OK, MessageBoxImage.Error); diff --git a/Elwig/Helpers/Printing/PdfPrintDocument.cs b/Elwig/Helpers/Printing/PdfPrintDocument.cs new file mode 100644 index 0000000..b2bd528 --- /dev/null +++ b/Elwig/Helpers/Printing/PdfPrintDocument.cs @@ -0,0 +1,102 @@ +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); + } +} diff --git a/Elwig/Windows/AboutWindow.xaml b/Elwig/Windows/AboutWindow.xaml index de2d833..edb7c7e 100644 --- a/Elwig/Windows/AboutWindow.xaml +++ b/Elwig/Windows/AboutWindow.xaml @@ -22,7 +22,7 @@ Programmiersprache: C# Framework: Windows Presentation Framework (WPF) Datenbank: SQLite - PDF-Erstellung: WeasyPrint, RazorLight, PdfiumViewer + PDF-Erstellung: WeasyPrint, RazorLight, Pdfium Paketierung: WiX Toolset diff --git a/README.md b/README.md index a1f32e4..e7a2d0e 100644 --- a/README.md +++ b/README.md @@ -43,5 +43,5 @@ Packaging: [WiX Toolset](https://www.firegiant.com/wixtoolset/) Programmiersprache: C# Framework: Windows Presentation Framework (WPF) Datenbank: [SQLite](https://sqlite.org/) -PDF-Erstellung: [WeasyPrint](https://weasyprint.org/), [RazorLight](https://github.com/toddams/RazorLight), [PdfiumViewer](https://github.com/pvginkel/PdfiumViewer) +PDF-Erstellung: [WeasyPrint](https://weasyprint.org/), [RazorLight](https://github.com/toddams/RazorLight), [Pdfium](https://github.com/bblanchon/pdfium-binaries) Paketierung: [WiX Toolset](https://www.firegiant.com/wixtoolset/)