HotPDF печата зареден PDF файл към физически принтер, всеки контекст на устройство на Windows (Device Context) или към клипборда чрез три извиквания: PrintLoadedDocument управлява VCL TPrinter, RenderLoadedPageToDC изчертава страница директно във всеки HDC, а RenderLoadedPageToClipboard копира страница като растерно изображение (bitmap) или векторен метафайл (EMF). HotPDF е нативен VCL PDF компонент за Delphi и C++Builder и добави този висококачествен път за печат във версия v2.331.0, като го подобри във версия v2.348.0, така че вече не се налага сами да изграждате цикъл с TPrinter около растерния визуализатор. И трите извиквания изчертават векторното съдържание на страницата директно там, където е необходимо, така че разпечатката остава толкова ясна, колкото принтерът може да я рендира
Защо да изчертавате PDF страница директно в принтера, вместо да използвате растерно изображение?
PDF страницата е програма от векторни оператори за изчертаване – пътеки, текст и изображения, изпълнявани спрямо графичния модел ISO 32000-1 – а не мрежа от пиксели. Очевидният начин да се отпечата такава страница е да се растеризира до растерно изображение (bitmap) и да се прехвърли върху платното на принтера, което работи, но изхвърля единственото нещо, в което принтерът е наистина добър. Съвременният лазерен принтер поддържа разделителна способност от 600 или 1200 DPI; растерното изображение, растеризирано при 150 или 300 DPI и след това разтегнато, изглежда меко, с назъбени краища на текста и видима интерполация. Методът RenderLoadedPageToDC избира по-добрия начин: той възпроизвежда потока от съдържание на страницата като GDI повиквания, изпратени директно към целевия контекст на устройството, така че векторният текст и векторните графики достигат до принтера като вектори и се растеризират еднократно от самия принтер при неговата собствена разделителна способност
Как да отпечатате зареден PDF на физически принтер в Delphi?
HotPDF отпечатва зареден документ с функцията PrintLoadedDocument(Printer, Options), която приема зададен VCL TPrinter и структура THPDFPrintOptions, отпечатва избраните страници и връща броя на изпратените страници. Първо задайте Printer.PrinterIndex, за да бъде избрано устройството, попълнете структурата с опции – функцията на класа THPDFPrintOptions.Default ви дава разумни стойности по подразбиране – и го извикайте. Библиотеката отваря задачата с Printer.BeginDoc, обхожда обхвата от страници, изпращайки Printer.NewPage между страниците, и я затваря с Printer.EndDoc, така че никога не управлявате жизнения цикъл на задачата за печат ръчно
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;
Как DPI и FitPage определят мащаба на печат?
Свойствата FitPage и DPI си взаимодействат по начин, който си струва да разберете преди разпространение. При стойност FitPage True – по подразбиране – HotPDF чете MediaBox на всяка страница, мащабира го спрямо Printer.PageWidth и Printer.PageHeight, като запазва съотношението на страните, и рендира с мащаб, който запълва хартията. В този режим параметърът Options.DPI се пренебрегва от мащаба на напасване, тъй като изходът трябва да съответства на физическите размери на страницата на принтера. При FitPage False, HotPDF рендира всяка страница 1:1 точно при Options.DPI, съпоставяйки 72 PDF единици към DPI хардуерни пиксела – това е подходящият избор, когато изходната страница и хартията вече са с еднакъв размер и ви е нужна точна разделителна способност. Използвайте FitPage, когато размерите на изходната страница и формата на хартията се различават; използвайте 1:1, когато те съвпадат и искате предвидимо мащабиране
Две опции, добавени във версия v2.348.0, коригират разпечатките, които изглеждат почти добре. Всеки физически принтер има твърдо поле (hard margin) – област без печат, която хардуерът не може да достигне, и по подразбиране началото на страницата попада там, поради което страница без бели полета губи ивица от двата края. Задайте IgnoreHardMargin на True и HotPDF ще извлече стойностите на принтера PHYSICALOFFSETX и PHYSICALOFFSETY, след което ще измести началото на устройството, за да елиминира това отместване, така че началото на страницата да съвпадне с истинския ъгъл на хартията. Втората опция, AutoRotate, е активирана по подразбиране: тя разчита MediaBox на всяка страница и когато страницата е по-широка, отколкото висока, превключва принтера в пейзажна ориентация (landscape), така че широката страница се отпечатва без изрязване. AutoRotate се деактивира автоматично, когато зададете ориентацията изрично, така че съзнателният избор на ориентация винаги има предимство
Как да рендирате PDF страница във всеки контекст на устройство (Device Context)?
Методът RenderLoadedPageToDC(PageIndex, DC, DPI, W, H) е основната функция под цикъла за печат и е полезен сам по себе си. PrintLoadedDocument го извиква по веднъж на страница за платното на принтера, но целта може да бъде всеки Windows HDC: невидима в паметта графична област (memory DC), платно на контрол в потребителски визуализатор или повърхност за предварителен преглед на печата. Параметърът PageIndex е нулев базиран, а W и H са мерните единици на целевата повърхност; рендиращият механизъм обхожда /Contents на страницата и изпраща GDI повиквания към вашия DC. Важно поведение на метода е, че той не запълва фона. Извикващият код притежава повърхността, така че ако искате бяла хартия зад страницата, трябва сами да запълните DC с бял цвят преди рендирането, което ви позволява да наслагвате страницата над съществуващо платно, когато пожелаете
// 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;
Как да поставите PDF страница в Word или графичен редактор?
Методът RenderLoadedPageToClipboard(PageIndex, DPI, AsMetafile) изпраща една страница в клипборда на Windows, готова за поставяне в Word, PowerPoint, имейл или графичен редактор. Флагът AsMetafile избира формата, като този избор е по-важен, отколкото изглежда. Предайте False и HotPDF ще постави 24-битово растерно изображение (CF_BITMAP), рендирано при избрания от вас DPI – фиксирана мрежа от пиксели, която може да се постави навсякъде, но се пикселизира, когато получателят я увеличи. Предайте True и методът ще постави подобрен метафайл (CF_ENHMETAFILE), в който текстовите и векторните графики на страницата се пренасят като GDI команди за чертане, така че поставеният резултат остава ясен при всякакво увеличение и се напасва към размера, определен от целевия документ
// 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);
Къде спира пътят за печат
Всичко на тази страница е валидно само за Windows и това трябва да се отбележи ясно. Функциите PrintLoadedDocument, RenderLoadedPageToDC и RenderLoadedPageToClipboard са изградени върху TPrinter, модела за контекст на устройство GDI, клипборда на Windows и подобрените метафайлове – всички те са Win32 и Win64 структури. За други платформи останалата част от HotPDF продължава да създава, редактира и чете PDF, но тази GDI-базирана функционалност за печат и клипборд не е налична. Рендиращият механизъм също така поддържа общия подмножествен набор от текст, пътеки и изображения, така че проекти с много градиенти и управление на цветовете по ICC се отпечатват като достоверно визуално превю, а не като цветово калибрирана проба – същото ограничение, което има и растерният визуализатор
За пакетен печат на множество файлове зареждайте и печатайте всеки документ последователно и следете разхода на памет: PrintLoadedDocument рендира по една страница в даден момент, но структурата на заредения документ остава в паметта през цялото времетраене на задачата. Когато управлявате опашка за печат от стотици големи файлове, стрийминг интерфейсът Direct File API за големи PDF файлове си партнира отлично с пътя за печат – разделете, обединете или изберете страниците на диска първо, след което заредете само олекотения резултат за печат. По този начин PrintLoadedDocument, RenderLoadedPageToDC и RenderLoadedPageToClipboard се доставят като част от HotPDF Component за Delphi и C++Builder – нативна VCL библиотека без външни DLL зависимости, покриваща генериране, редактиране, извличане на текст, рендиране и печат директно към TPrinter, всеки контекст на устройство или клипборда