Artikel Teknis

Mencetak PDF yang Dimuat di Delphi dengan HotPDF dan TPrinter

HotPDF mencetak PDF yang dimuat ke printer fisik, konteks perangkat (device context) Windows mana pun, atau clipboard melalui tiga panggilan: PrintLoadedDocument menggerakkan VCL TPrinter, RenderLoadedPageToDC melukis halaman langsung ke HDC mana pun, dan RenderLoadedPageToClipboard menyalin halaman sebagai bitmap atau metafile vektor. HotPDF adalah komponen PDF VCL asli untuk Delphi dan C++Builder, dan ia menambahkan jalur cetak kelas utama ini di v2.331.0, serta menyempurnakannya di v2.348.0, sehingga Anda tidak perlu lagi membuat perulangan TPrinter sendiri di sekitar renderer bitmap. Ketigasa panggilan tersebut menggambar konten vektor halaman secara langsung di tempat yang diperlukan, sehingga hasil cetak tetap setajam yang dapat dirender oleh printer

Mengapa menggambar halaman PDF langsung ke printer alih-alih ke bitmap?

Halaman PDF adalah serangkaian operator gambar vektor — jalur, teks, dan gambar yang dijalankan terhadap model grafis ISO 32000-1 — bukan kisi piksel. Cara yang jelas untuk mencetaknya adalah dengan merasterisasi halaman menjadi bitmap dan menyalin (blit) bitmap tersebut ke kanvas printer, dan itu berhasil, tetapi membuang satu-satunya keahlian utama printer. Printer laser modern dapat mencapai resolusi 600 atau 1200 DPI; bitmap yang dirasterisasi pada 150 atau 300 DPI lalu diregangkan agar muat akan tampak lembut (buram), dengan tepi teks yang bergerigi dan interpolasi yang terlihat. RenderLoadedPageToDC mengambil jalur yang lebih baik: ia memutar ulang stream konten halaman sebagai panggilan GDI yang dipancarkan langsung ke konteks perangkat target, sehingga teks vektor dan seni garis mencapai printer sebagai vektor dan dirasterisasi sekali oleh printer pada resolusi printer itu sendiri

How do you print a loaded PDF to a physical printer in Delphi?

Bagaimana cara mencetak PDF yang dimuat ke printer fisik di Delphi?

HotPDF mencetak dokumen yang dimuat dengan PrintLoadedDocument(Printer, Options), yang menerima VCL TPrinter yang ditentukan dan rekaman THPDFPrintOptions, mencetak halaman yang dipilih, dan mengembalikan jumlah halaman yang dikirim. Atur Printer.PrinterIndex terlebih dahulu agar perangkat terpilih, isi rekaman opsi — fungsi kelas THPDFPrintOptions.Default memberi Anda nilai yang masuk akal — dan panggil sekali. Pustaka membuka pekerjaan cetak dengan Printer.BeginDoc, menelusuri rentang halaman dengan memancarkan Printer.NewPage antar halaman, dan menutupnya dengan Printer.EndDoc, sehingga Anda tidak perlu mengelola siklus hidup pekerjaan cetak secara manual

uses Printers;

var
  Pdf: THotPDF;
  Opts: THPDFPrintOptions;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('invoice.pdf') > 0 then
    begin
      Printer.PrinterIndex := -1;         // -1 selects the default printer
      Opts := THPDFPrintOptions.Default;  // all pages, 300 DPI, FitPage, colour
      Opts.PageRange := '1,3-5';          // one-based; empty prints every page
      Opts.Copies := 2;
      Pdf.PrintLoadedDocument(Printer, Opts);
    end;
  finally
    Pdf.Free;
  end;
end;

String PageRange berbasis satu dan dibaca seperti halnya dialog cetak: '1,3-5' mencetak halaman 1 dan halaman 3 hingga 5, dan string kosong mencetak seluruh dokumen. Copies memetakan langsung ke Printer.Copies. Namun, jujurlah pada diri sendiri tentang Collate: karena VCL mengekspos kolasi secara tidak konsisten di berbagai versi Delphi, HotPDF menetapkan jumlah salinan dan menyerahkan kolasi ke bawaan driver printer, jadi ketika Anda memerlukan urutan kolasi yang terjamin, atur pada driver melalui TPrinterSetupDialog daripada mempercayai bendera tersebut untuk membawanya

Bagaimana DPI dan FitPage menentukan skala cetak?

FitPage dan DPI berinteraksi dengan cara yang patut dipahami sebelum Anda mendistribusikan aplikasi. Dengan FitPage bernilai True — bawaan — HotPDF membaca MediaBox setiap halaman, menskalakannya ke Printer.PageWidth dan Printer.PageHeight dengan mempertahankan rasio aspek, dan merender pada skala yang membuat halaman memenuhi kertas. Dalam mode tersebut, Options.DPI secara efektif ditimpa oleh skala pencocokan (fit scale), karena output harus cocok dengan dimensi halaman fisik printer. Dengan FitPage bernilai False, HotPDF merender setiap halaman 1:1 tepat pada Options.DPI, memetakan 72 unit PDF ke piksel perangkat DPI, yang merupakan apa yang Anda inginkan ketika halaman sumber dan kertas sudah berukuran sama dan Anda peduli dengan resolusi yang tepat. Gunakan FitPage ketika ukuran halaman sumber dan ukuran baki kertas berbeda; gunakan 1:1 ketika keduanya cocok dan Anda menginginkan penskalaan deterministik

Dua opsi yang ditambahkan di v2.348.0 memperbaiki hasil cetak yang terlihat hampir benar. Setiap printer fisik memiliki hard margin — batas non-cetak yang tidak dapat dijangkau oleh perangkat keras — dan secara bawaan titik asal halaman mendarat di dalamnya, sehingga halaman full-bleed kehilangan potongan di kedua tepinya. Atur IgnoreHardMargin ke True dan HotPDF akan meminta PHYSICALOFFSETX dan PHYSICALOFFSETY milik printer, lalu menggeser titik asal perangkat untuk membatalkan offset tersebut sehingga titik asal halaman memetakan ke sudut kertas yang sebenarnya. Opsi kedua, AutoRotate, aktif secara bawaan: ia membaca MediaBox setiap halaman dan, ketika halaman lebih lebar daripada tingginya, membalik printer ke mode lanskap sehingga halaman yang lebar tercetak tanpa terpotong daripada dipotong menjadi potret. AutoRotate akan menyingkir saat Anda mengatur Orientation secara eksplisit, sehingga pilihan orientasi yang disengaja selalu menang

Bagaimana cara merender halaman PDF ke dalam konteks perangkat mana pun?

RenderLoadedPageToDC(PageIndex, DC, DPI, W, H) adalah primitif di bawah perulangan cetak, dan berguna secara tersendiri. PrintLoadedDocument memanggilnya sekali per halaman terhadap kanvas printer, tetapi targetnya dapat berupa Windows HDC mana pun: memori DC di luar layar, kanvas kontrol dalam viewer kustom, atau permukaan pratinjau cetak. PageIndex berbasis nol, W dan H adalah unit perangkat dari permukaan target, dan renderer menelusuri /Contents halaman serta memancarkan panggilan GDI ke DC Anda. Satu perilaku yang disengaja patut diketahui: ia tidak menggambar pengisian latar belakang. Peminstaller memiliki permukaan tersebut, jadi jika Anda ingin kertas putih di belakang halaman, Anda mengisi sendiri DC tersebut sebelum merender, yang memungkinkan Anda membuat komposit halaman di atas kanvas yang ada saat Anda menginginkannya

// Draw page 1 into an off-screen 24-bit surface at 150 DPI
var
  Surface: TBitmap;
begin
  Surface := TBitmap.Create;
  try
    Surface.PixelFormat := pf24bit;
    Surface.SetSize(1275, 1650);           // 8.5 x 11 in at 150 DPI
    Surface.Canvas.Brush.Color := clWhite;
    Surface.Canvas.FillRect(Surface.Canvas.ClipRect);  // caller paints the background
    Pdf.RenderLoadedPageToDC(0, Surface.Canvas.Handle, 150, Surface.Width, Surface.Height);
    // Surface now holds the composited page, ready to blit or save
  finally
    Surface.Free;
  end;
end;

Bila Anda hanya membutuhkan TBitmap yang sudah jadi — thumbnail, ekspor gambar, atau pratinjau yang akan Anda cache — gunakan RenderLoadedPageToBitmap sebagai gantinya, yang dibahas dalam artikel pendamping tentang merender halaman PDF ke bitmap. Perbedaannya adalah siapa yang memiliki permukaan: panggilan bitmap mengalokasikan dan mengembalikan buffer piksel, sedangkan RenderLoadedPageToDC menggambar ke dalam konteks perangkat yang sudah Anda miliki, yang merupakan apa yang diberikan oleh kanvas printer atau handler cat kepada Anda. Keduanya berbagi interpreter stream konten dan engine glyph tersemat yang sama, sehingga teks keluar dengan garis luar tersemat yang tepat dengan cara apa pun

Bagaimana cara menempelkan halaman PDF ke Word atau editor gambar?

RenderLoadedPageToClipboard(PageIndex, DPI, AsMetafile) menempatkan satu halaman di clipboard Windows, siap ditempelkan ke Word, PowerPoint, email, atau editor gambar. Bendera AsMetafile memilih formatnya, dan pilihan tersebut lebih penting daripada yang terlihat. Berikan nilai False dan HotPDF akan menempatkan bitmap perangkat 24-bit (CF_BITMAP) yang dirender pada DPI Anda — kisi piksel tetap yang dapat ditempel di mana saja tetapi akan pecah saat penerima memperbesarnya. Berikan nilai True dan ia akan menempatkan enhanced metafile (CF_ENHMETAFILE) di mana teks dan seni vektor halaman berjalan sebagai perintah gambar GDI, sehingga hasil yang ditempelkan tetap tajam pada perbesaran apa pun dan mengalir ulang (reflow) ke ukuran apa pun yang diberikan dokumen tujuan

// Copy page 2 as a scalable vector metafile for pasting into Word
Pdf.RenderLoadedPageToClipboard(1, 300, True);

// Copy the same page as a fixed 300-DPI bitmap instead
Pdf.RenderLoadedPageToClipboard(1, 300, False);

Aturan praktisnya sederhana. Jika manusia akan menempelkan halaman tersebut ke dalam dokumen dan mungkin mengubah ukurannya — gambar dalam laporan, klausul yang dimasukkan ke dalam draf kontrak — gunakan metafile, karena teks vektor dapat dicetak dan diperbesar secara bersih. Jika tujuan hanya memahami data raster, atau Anda secara khusus menginginkan snapshot beku pada resolusi yang diketahui, gunakan bitmap. Untuk menarik kata-kata keluar dari halaman daripada sekadar gambarnya, itu adalah pekerjaan yang sama sekali berbeda, yang ditangani oleh API ekstraksi teks, yang mengembalikan karakter beserta posisinya daripada gambar yang dirender

Di mana batas jalur cetak

Semua yang ada di halaman ini khusus untuk Windows, dan ini patut dinyatakan dengan jelas. PrintLoadedDocument, RenderLoadedPageToDC, dan RenderLoadedPageToClipboard dibangun di atas TPrinter, model device-context GDI, clipboard Windows, and enhanced metafiles — semuanya merupakan konstruksi Win32 dan Win64. Pada target lain, sisa HotPDF tetap membuat, mengedit, dan membaca PDF, tetapi cetak berbasis GDI dan permukaan clipboard ini tidak tersedia. Renderer juga menargetkan subset dokumen umum dari teks, jalur, dan gambar, sehingga bukti desain yang sarat gradien dan cetak warna yang dikelola ICC tercetak sebagai pratinjau yang setia daripada bukti kolorimetri, batas yang sama yang dibawa oleh renderer bitmap

Untuk pencetakan batch di banyak file, muat dan cetak setiap dokumen secara bergantian dan perhatikan penggunaan memori: PrintLoadedDocument merender satu halaman pada satu waktu, tetapi grafik dokumen yang dimuat itu sendiri tetap berada di memori selama seluruh pekerjaan. Ketika Anda menggerakkan antrean cetak di atas ratusan file besar, streaming Direct File API untuk alur kerja PDF besar berpasangan baik dengan jalur cetak — pisahkan, gabungkan, atau pilih halaman yang Anda butuhkan di disk terlebih dahulu, lalu muat hanya hasil yang ringkas untuk dicetak. Itulah bagaimana PrintLoadedDocument, RenderLoadedPageToDC, dan RenderLoadedPageToClipboard didistribusikan sebagai bagian dari HotPDF Component untuk Delphi dan C++Builder — pustaka VCL asli tanpa dependensi DLL eksternal yang mencakup pembuatan, pengeditan, ekstraksi teks, rendering PDF, dan sekarang pencetakan langsung ke TPrinter, konteks perangkat apa pun, atau clipboard