Techninis straipsnis

Įkelto PDF spausdinimas Delphi aplinkoje naudojant HotPDF ir TPrinter

HotPDF spausdina įkeltą PDF dokumentą fiziniu spausdintuvu, bet kuriame „Windows“ įrenginio kontekste arba nukopijuoja į iškarpinę per tris iškvietimus: PrintLoadedDocument valdo VCL TPrinter, RenderLoadedPageToDC nupiešia puslapį tiesiai į bet kurį HDC, o RenderLoadedPageToClipboard nukopijuoja puslapį kaip rastrinį paveikslėlį arba vektorinį metafailą. HotPDF yra vietinis VCL PDF komponentas, skirtas Delphi ir C++Builder, ir jis šį pirmos klasės spausdinimo kelią pridėjo v2.331.0 versijoje bei patobulino v2.348.0 versijoje, todėl jums nebereikia patiems rankiniu būdu kurti TPrinter ciklo aplink rastrinių vaizdų atvaizduotoją. Veliuokite, visi trys iškvietimai piešia puslapio vektorinį turinį tiesiai ten, kur reikia, todėl spaudinys išlieka toks aštrus, kokį tik spausdintuvas gali atvaizduoti

Kodėl verta piešti PDF puslapį tiesiai į spausdintuvą, o ne į taškinį vaizdą?

PDF puslapis yra vektorinio piešimo operatorių programa — keliai, tekstas ir vaizdai, vykdomi pagal ISO 32000-1 grafikos modelį —, o ne pikselių tinklelis. Akivaizdus būdas jį atspausdinti yra rastruoti puslapį į taškinį vaizdą ir perkelti jį ant spausdintuvo drobės; tai veikia, tačiau išmeta vienintelį dalyką, kuriuo spausdintuvas yra pranašus. Modernus lazerinis spausdintuvas pasižymi 600 arba 1200 DPI raiška; taškinis vaizdas, rastruotas 150 arba 300 DPI raiška, o po to ištemptas, atspausdinamas blankiai, su dantytomis teksto briaunomis ir matoma interpoliacija. RenderLoadedPageToDC pasirenka geresnį kelią: atkuria puslapio turinio srautą kaip GDI iškvietimus, nukreiptus tiesiai į tikslinio įrenginio kontekstą, todėl vektorinis tekstas ir linijos pasiekia spausdintuvą kaip vektoriai ir yra rastruojami tik vieną kartą, paties spausdintuvo, jo paties raiška

Kaip Delphi aplinkoje atspausdinti įkeltą PDF fiziniu spausdintuvu?

HotPDF spausdina įkeltą dokumentą su PrintLoadedDocument(Printer, Options), kuris priima priskirtą VCL TPrinter bei THPDFPrintOptions įrašą, išspausdina pasirinktus puslapius ir grąžina nusiųstų puslapių skaičių. Pirmiausia nustatykite Printer.PrinterIndex, kad būtų pasirinktas įrenginys, užpildykite parinkčių įrašą — THPDFPrintOptions.Default klasės funkcija suteikia jums protingas reikšmes — ir iškvieskite ją vieną kartą. Biblioteka atidaro užduotį su Printer.BeginDoc, pereina puslapių diapazoną įterpdama Printer.NewPage tarp puslapių ir uždaro ją su Printer.EndDoc, todėl jums nereikia rankiniu būdu valdyti spausdinimo užduoties gyvavimo ciklo

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;

PageRange eilutė yra pagrįsta vienetu ir skaitoma taip pat, kaip spausdinimo dialogo lange: '1,3-5' atspausdina 1 puslapį bei puslapius nuo 3 iki 5, o tuščia eilutė atspausdina visą dokumentą. Copies nukreipiamas tiesiai į Printer.Copies. Tačiau būkite atviri dėl Collate (rūšiavimo): kadangi VCL atskleidžia rūšiavimą nevienodai skirtingose Delphi versijose, HotPDF nustato kopijų skaičių ir palieka rūšiavimą spausdintuvo tvarkyklės numatytajam nustatymui, todėl kai jums reikia garantuotos rūšiavimo tvarkos, nustatykite ją tvarkyklėje per TPrinterSetupDialog, užuot pasitikėję šia vėliavėle

Kaip DPI ir FitPage decide spausdinimo mastelį?

FitPage ir DPI sąveikauja taip, kad tai verta suprasti prieš diegiant programą. Kai FitPage yra True (numatytasis nustatymas), HotPDF nuskaito kiekvieno puslapio MediaBox, pritaiko jį prie Printer.PageWidth ir Printer.PageHeight, išlaikydamas kraštinių santykį, ir atvaizduoja tokiu masteliu, kad puslapis užpildytų popierių. Šiame režime Options.DPI yra veiksmingai pakeičiamas pritaikymo masteliu, nes išvestis turi atitikti fizinius spausdintuvo puslapio matmenis. Kai FitPage yra False, HotPDF atvaizduoja kiekvieną puslapį santykiu 1:1 tiksliai pagal Options.DPI, susiedamas 72 PDF vienetus su DPI įrenginio pikseliais; to norite, kai šaltinio puslapis ir popierius jau yra vienodo dydžio ir jums rūpi tiksli raiška. Naudokite „FitPage“, kai šaltinio puslapio dydis ir dėklo dydis skiriasi; naudokite santykį 1:1, kai jie sutampa ir norite deterministinio mastelio keitimo

Dvi parinktys, pridėtos v2.348.0 versijoje, ištaiso spaudinius, kurie atrodo beveik teisingai. Kiekvienas fizinis spausdintuvas turi kietąją paraštę — nespausdinamą rėmelį, kurio techninė įranga negali pasiekti —, ir pagal nutylėjimą puslapio pradžios taškas patenka į jos vidų, todėl pilno spaudinio puslapis praranda juostą dviejuose kraštuose. Nustatykite IgnoreHardMargin į True ir HotPDF užklaus spausdintuvo PHYSICALOFFSETX bei PHYSICALOFFSETY, tada pastums įrenginio koordinačių pradžią, kad atšauktų šį nuokrypį, o puslapio pradžia sutaptų su tikruoju popieriaus kampu. Antroji parinktis, AutoRotate, yra įjungta pagal nutylėjimą: ji nuskaito kiekvieno puslapio MediaBox ir, kai puslapis yra platesnis nei aukštesnis, perjungia spausdintuvą į gulsčią padėtį, kad platus puslapis būtų atspausdintas nenukirptas. AutoRotate pasitraukia tą akimirką, kai nustatote Orientation aiškiai, todėl sąmoningas orientacijos pasirinkimas visada laimi

Kaip atvaizduoti PDF puslapį bet kuriame įrenginio kontekste?

RenderLoadedPageToDC(PageIndex, DC, DPI, W, H) yra primityvas po spausdinimo ciklu, ir jis yra naudingas pats savaime. PrintLoadedDocument iškviečia jį po kartą kiekvienam puslapiai spausdintuvo drobėje, tačiau tikslas gali būti bet koks „Windows“ HDC: atmintyje esantis DC, valdiklio drobė pasirinktinėje peržiūros programoje arba spausdinimo peržiūros paviršius. PageIndex yra pagrįstas nuliu, W ir H yra tikslinio paviršiaus įrenginio vienetai, o atvaizduotojas pereina puslapio /Contents ir siunčia GDI iškvietimus į jūsų DC. Verta žinoti vieną sąmoningą elgseną: jis nepiešia jokio fono užpildymo. Paviršius priklauso iškvietėjui, todėl jei po puslapiu norite balto popieriaus, prieš atvaizdavimą patys užpildote DC; būtent tai leidžia uždėti puslapį ant esamos drobės, kai to norite

Kai jums tiesiog reikia paruošto TBitmap — eskizo, vaizdo eksporto, peržiūros, kurią talpinsite atmintyje —, naudokite RenderLoadedPageToBitmap, aprašytą susijusiame straipsnyje apie PDF puslapių atvaizdavimą taškiniame vaizde. Skirtumas yra tas, kam priklauso paviršius: bitmap iškvietimas išskiria ir grąžina pikselių buferį, o RenderLoadedPageToDC piešia į įrenginio kontekstą, kurį jau turite, pavyzdžiui, spausdintuvo drobėje arba piešimo apdorojimo programoje. Abu naudoja tą patį turinio srauto interpretatorių ir įterptųjų glifų variklį, todėl tekstas bet kuriuo atveju atvaizduojamas su tikslais įterptais kontūrais

Kaip įklijuoti PDF puslapį į „Word“ arba vaizdų redaktorių?

RenderLoadedPageToClipboard(PageIndex, DPI, AsMetafile) padeda vieną puslapį į „Windows“ iškarpinę, paruoštą įklijuoti į „Word“, „PowerPoint“, el. laišką ar vaizdo redaktorių. Vėliavėlė AsMetafile parenka formatą, ir šis pasirinkimas yra svarbesnis, nei atrodo. Perduokite False ir HotPDF patalpins 24 bitų įrenginio bitmap (CF_BITMAP), atvaizduotą jūsų DPI — kai kur, tačiau praranda kokybę, kai gavėjas jį padidina. Perduokite True ir jis patalpins patobulintąjį metafailą (CF_ENHMETAFILE), kuriame puslapio tekstas ir vektorinis menas keliauja kaip GDI piešimo komandos, todėl įklijuotas rezultatas išlieka aštrus esant bet kokiam masteliui ir prisitaiko prie bet kokio dydžio, kurį jam suteikia tikslinis dokumentas

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

Kaip veikia teksto išgavimo API?

Pagrindinė taisyklė paprasta. Jei žmogus įklijuos puslapį į dokumentą ir gali keisti jo dydį — pavyzdžiui, diagramą ataskaitoje arba punktą sutarties projekte —, naudokite metafailą, nes vaizdo tekstas spausdinamas ir didinamas švariai. Jei tikslas supranta tik taškinius duomenis arba konkrečiai norite užfiksuotos nuotraukos tam tikra raiška, naudokite bitmap. Žodžių išgavimui iš puslapio, o ne jų atvaizdui gauti, skirtas visiškai kitas darbas, kurį atlieka teksto išgavimo API, grąžinanti simbolius bei jų pozicijas, o ne atvaizduotą vaizdą

Kur sustoja spausdinimo kelias

Viskas šiame puslapyje yra skirta tik „Windows“ operacinei sistemai, ir tai verta pasakyti aiškiai. PrintLoadedDocument, RenderLoadedPageToDC ir RenderLoadedPageToClipboard yra sukurti remiantis TPrinter, GDI įrenginio konteksto modeliu, „Windows“ iškarpine ir patobulintaisiais metafailais — visa tai yra Win32 bei Win64 konstrukcijos. Kitose platformose likusi HotPDF dalis vis tiek kuria, redaguoja ir skaito PDF, tačiau šis GDI pagrindu veikiantis spausdinimo ir iškarpinės paviršius yra neprieinamas. Atvaizduotojas taip pat yra pritaikytas įprastam dokumento poaibiui — tekstui, keliams ir vaizdams —, todėl maketai su daug gradientų bei ICC valdomos spalvos atspausdinamos kaip tiksli peržiūra, o ne kolorimetrinis atspaudas — tai ta pati riba, kurią turi ir bitmap atvaizduotojas

Spausdinant paketais daug failų, įkelkite ir atspausdinkite kiekvieną dokumentą paeiliui ir stebėkite atminties sąnaudas: PrintLoadedDocument atvaizduoja po vieną puslapį vienu metu, tačiau pats įkelto dokumento grafikas išlieka atmintyje visos užduoties metu. Kai valdote spausdinimo eilę iš šimtų didelių failų, srautinis Direct File API, skirtas didelių PDF apdorojimui, puikiai dera su spausdinimo keliu — pirmiausia diske padalykite, sujunkite arba pasirinkite reikiamus puslapius, o tada įkelkite tik nedidelį rezultatą spausdinimui. Būtent taip PrintLoadedDocument, RenderLoadedPageToDC ir RenderLoadedPageToClipboard platinami kaip HotPDF komponento, skirto Delphi ir C++Builder, dalis — vietinė VCL biblioteka be išorinių DLL priklausomybių, kuri apima PDF kūrimą, redagavimą, teksto išgavimą, atvaizdavimą, o dabar ir spausdinimą tiesiai į TPrinter, bet kurį įrenginio kontekstą arba iškarpinę