Technický článok

Tlač načítaného PDF v Delphi pomocou HotPDF a TPrinter

HotPDF tlačí načítané PDF na fyzickú tlačiareň, akýkoľvek kontext zariadenia Windows (device context) alebo do schránky (clipboard) prostredníctvom troch volaní: PrintLoadedDocument ovláda VCL TPrinter, RenderLoadedPageToDC vykresľuje stránku priamo do akéhokoľvek HDC a RenderLoadedPageToClipboard kopíruje stránku ako bitmapu alebo vektorový metasúbor. HotPDF je natívny VCL PDF komponent pre Delphi a C++Builder a túto prvotriednu tlačovú cestu pridal vo verzii v2.331.0 a vylepšil vo verzii v2.348.0, takže už nemusíte sami ručne prepájať slučku TPrinter s bitmapovým vykresľovačom. Všetky tri volania kreslia vektorový obsah stránky priamo tam, kde na tom záleží, takže výtlačok zostáva taký ostrý, ako ho tlačiareň dokáže vykresliť

Prečo kresliť PDF stránku priamo do tlačiarne namiesto bitmapy?

Stránka PDF je programom vektorových kresliacich operátorov — ciest, textu a obrázkov spustených voči grafickému modelu ISO 32000-1 — a nie mriežkou pixelov. Zrejmým spôsobom, ako ju vytlačiť, je rasterizovať stránku do bitmapy a preniesť (blit) túto bitmapu na plátno (canvas) tlačiarne. To síce funguje, ale zahadzuje to jedinú vec, v ktorej je tlačiareň dobrá. Moderná laserová tlačiareň rozlišuje 600 alebo 1200 DPI; bitmapa rasterizovaná pri 150 alebo 300 DPI a potom roztiahnutá, aby sa prispôsobila, prichádza neostrá, s kostrbatými okrajmi textu a viditeľnou interpoláciou. Metóda RenderLoadedPageToDC využíva lepšiu cestu: prehráva tok obsahu stránky ako volania GDI vysielané priamo do cieľového kontextu zariadenia, takže vektorový text a čiarová grafika dorazia do tlačiarne ako vektory a rasterizujú sa iba raz, a to samotnou tlačiarňou pri jej vlastnom rozlíšení

Ako vytlačiť načítané PDF na fyzickú tlačiareň v Delphi?

HotPDF tlačí načítaný dokument pomocou PrintLoadedDocument(Printer, Options), čo vyžaduje priradený VCL TPrinter a záznam THPDFPrintOptions, vytlačí vybrané stránky a vráti počet odoslaných stránok. Najprv nastavte Printer.PrinterIndex, aby sa vybralo zariadenie, vyplňte záznam možností — funkcia triedy THPDFPrintOptions.Default vám poskytne rozumné hodnoty — a zavolajte ju. Knižnica otvorí úlohu pomocou Printer.BeginDoc, prechádza rozsah stránok, pričom medzi nimi vysiela Printer.NewPage, a zatvorí ju pomocou Printer.EndDoc, takže životný cyklus tlačovej úlohy nikdy neriadite ručne

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;

Reťazec PageRange sa indexuje od 1 a číta sa tak, ako v dialógovom okne tlače: '1,3-5' vytlačí stránku 1 a stránky 3 až 5, pričom prázdny reťazec vytlačí celý dokument. Copies (Kópie) sa mapuje priamo na Printer.Copies. Buďte k sebe úprimní, pokiaľ ide o Collate (Triedenie): pretože VCL vystavuje triedenie nekonzistentne naprieč verziami Delphi, HotPDF nastaví počet kópií a triedenie ponechá na predvolené nastavenie ovládača tlačiarne, takže ak potrebujete garantované poradie triedenia, nastavte ho na ovládači prostredníctvom TPrinterSetupDialog a nespoliehajte sa na to, že ho prenesie príznak

Ako DPI a FitPage určujú mierku tlače?

Interakcia medzi FitPage (Prispôsobiť stránke) a DPI stojí za pochopenie predtým, než produkt vydáte. Keď je FitPage True (predvolené), HotPDF načíta MediaBox každej stránky, prispôsobí ho pre Printer.PageWidth and Printer.PageHeight so zachovaním pomeru strán a vykreslí ho v mierke, ktorá vyplní papier. V tomto režime je Options.DPI efektívne potlačené mierkou prispôsobenia, pretože výstup musí zodpovedať fyzickým rozmerom stránky tlačiarne. Keď je FitPage False, HotPDF vykresľuje každú stránku v pomere 1:1 presne pri Options.DPI, pričom mapuje 72 jednotiek PDF na DPI pixelov zariadenia, čo je to, čo chcete, keď sú zdrojová stránka a papier už rovnakej veľkosti a záleží vám na presnom rozlíšení. Po FitPage siahnite vtedy, keď sa veľkosť zdrojovej stránky a veľkosť zásobníka líšia; po 1:1 siahnite vtedy, keď sa zhodujú a chcete dosiahnuť deterministické škálovanie

Dve možnosti pridané vo verzii v2.348.0 opravujú výtlačky, ktoré vyzerajú takmer správne. Každá fyzická tlačiareň má pevný okraj (hard margin) — netlačiteľný okraj, na ktorý hardvér nedosiahne — a predvolene počiatok stránky pristane v ňom, takže stránka s tlačou bez okrajov (full-bleed) stratí pásik z dvoch hrán. Nastavením IgnoreHardMargin na True sa HotPDF dotáže na PHYSICALOFFSETX a PHYSICALOFFSETY tlačiarne a potom posunie počiatok zariadenia, aby tento posun zrušil, takže počiatok stránky sa namapuje na skutočný roh papiera. Druhá možnosť, AutoRotate (Automatické otočenie), je predvolene zapnutá: načíta MediaBox každej stránky a keď je stránka širšia ako vysoká, otočí tlačiareň na šírku (landscape), takže široká stránka sa vytlačí neoorezaná namiesto toho, aby bola orezaná na výšku (portrait). AutoRotate ustúpi v momente, keď nastavíte Orientation (Orientáciu) explicitne, takže zámerná voľba orientácie vždy vyhráva

Ako vykresliť PDF stránku do akéhokoľvek kontextu zariadenia?

Metóda RenderLoadedPageToDC(PageIndex, DC, DPI, W, H) je primitívom pod tlačovou slučkou a je užitočná sama o sebe. PrintLoadedDocument ju volá raz na stránku voči plátnu tlačiarne, ale cieľom môže byť akékoľvek Windows HDC: off-screen pamäťové DC, plátno ovládacieho prvku v používateľskom prehliadači alebo povrch náhľadu pred tlačou. PageIndex sa indexuje od nuly, W a H sú jednotky zariadenia cieľového povrchu a vykresľovač prechádza /Contents stránky a vysiela volania GDI do vášho DC. Stojí za to poznať jedno zámerné správanie: nekreslí žiadnu výplň pozadia. Volajúci vlastní povrch, takže ak chcete mať pod stránkou biely papier, pred vykreslením vyplníte DC sami, čo je presne to, čo vám umožňuje komponovať stránku cez existujúce plátno, keď to potrebujete

// 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;

Keď potrebujete len hotový TBitmap — miniatúru, export obrázka, náhľad, ktorý budete ukladať do vyrovnávacej pamäte —, siahnite namiesto toho po RenderLoadedPageToBitmap, čo je popísané v sprievodnom článku o vykresľovaní PDF stránok do bitmapy. Rozdiel je v tom, kto vlastní povrch: volanie bitmapy alokuje a vracia pixelový buffer, zatiaľ čo RenderLoadedPageToDC kreslí do kontextu zariadenia, ktorý už držíte, čo je presne to, čo vám odovzdá plátno tlačiarne alebo obsluha vykresľovania. Obe zdieľajú rovnaký interpret toku obsahu a modul so zabudovanými glyfmi, takže text vyjde v oboch prípadoch s presnými zabudovanými obrysmi

Ako vložiť PDF stránku do Wordu alebo obrázkového editora?

Metóda RenderLoadedPageToClipboard(PageIndex, DPI, AsMetafile) umiestni jednu stránku do schránky Windows, pripravenú na vloženie do Wordu, PowerPointu, e-mailu alebo editora obrázkov. Príznak AsMetafile volí formát a táto voľba závisí na viacerých veciach než by sa zdalo. Ak odovzdáte False, HotPDF umiestni 24-bitovú bitmapu zariadenia (CF_BITMAP) vykreslenú pri vašom DPI — pevnú mriežku pixelov, ktorú je možné vložiť kamkoľvek, ale pri zväčšení príjemcom zpixelovatie. Ak odovzdáte True, umiestni rozšírený metasúbor (CF_ENHMETAFILE), v ktorom text a vektorová grafika stránky putujú ako príkazy na kreslenie GDI, takže vložený výsledok zostáva ostrý pri akomkoľvek priblížení a prispôsobí sa akejkoľvek veľkosti, ktorú mu cieľový dokument pridelí

// 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);

Základné pravidlo je jednoduché. Ak človek vloží stránku do dokumentu a môže zmeniť jej veľkosť — obrázok v správe, ustanovenie vložené do návrhu zmluvy —, použite metasúbor, pretože vektorový text sa tlačí a približuje čisto. Ak cieľ rozumie iba rastrovým dátam alebo ak vyslovene chcete zmrazenú snímku pri známom rozlíšení, použite bitmapu. Získanie slov zo stránky namiesto ich obrázka je úplne iná úloha, ktorú rieši API na extrakciu textu, ktoré vracia znaky a ich pozície namiesto vykresleného obrázka

Kde tlačová cesta končí

Všetko na tejto stránke je určené iba pre Windows a stojí za to uviesť to otvorene. Metódy PrintLoadedDocument, RenderLoadedPageToDC a RenderLoadedPageToClipboard sú postavené na TPrinter, modeli kontextu zariadenia GDI, schránke Windows a rozšírených metasúboroch — všetko sú to konštrukty Win32 a Win64. Na iných cieľových platformách zvyšok HotPDF stále vytvára, upravuje a číta PDF, ale toto tlačové rozhranie a rozhranie schránky podporované GDI nie je k dispozícii. Vykresľovač sa tiež zameriava na bežnú podmnožinu dokumentov s textom, cestami a obrázkami, takže návrhy s hustými prechodmi a farby riadené ICC sa vytlačia ako verný náhľad a nie ako kolorimetrický nátlačok, čo je rovnaká hranica, akú nesie bitmapový vykresľovač

Pri dávkovej tlači viacerých súborov načítajte a vytlačte každý dokument postupne a sledujte spotrebu pamäte: PrintLoadedDocument vykresľuje naraz jednu stránku, ale graf samotného načítaného dokumentu zostáva v pamäti počas celej úlohy. Keď riadite tlačový rad pre stovky veľkých súborov, streamované Direct File API pre prácu s veľkými PDF sa dobre dopĺňa s tlačovou cestou — najprv na disku rozdeľte, zlúčte alebo vyberte stránky, ktoré potrebujete, a potom na tlač načítajte iba štíhly výsledok. Týmto spôsobom sa metódy PrintLoadedDocument, RenderLoadedPageToDC a RenderLoadedPageToClipboard dodávajú ako súčasť komponentu HotPDF Component pre Delphi a C++Builder — natívnej VCL knižnice bez externých závislostí na DLL, ktorá pokrýva tvorbu, úpravu, extrakciu textu, vykresľovanie PDF a najnovšie aj tlač priamo do TPrinter, akéhokoľvek kontextu zariadenia alebo schránky