O HotPDF imprime um PDF carregado para uma impressora física, qualquer contexto de dispositivo do Windows ou para a área de transferência por meio de três chamadas: PrintLoadedDocument controla um TPrinter da VCL, RenderLoadedPageToDC pinta uma página diretamente em qualquer HDC, e RenderLoadedPageToClipboard copia uma página como um bitmap ou um meta-arquivo vetorial. O HotPDF é um componente PDF nativo de VCL para Delphi e C++Builder, e adicionou esse caminho de impressão de primeira classe na v2.331.0, refinando-o na v2.348.0, para que você não precise mais gerenciar manualmente um loop de TPrinter em torno de um renderizador de bitmap. Todas as três chamadas desenham o conteúdo vetorial da página diretamente onde é necessário, de modo que a impressão permanece tão nítida quanto a impressora possa renderizar
Por que desenhar uma página PDF diretamente na impressora em vez de um bitmap?
Uma página PDF é um programa de operadores de desenho vetorial — caminhos, textos e imagens executados contra o modelo gráfico ISO 32000-1 — não uma grade de pixels. A maneira óbvia de imprimir uma é rasterizar a página em um bitmap e transferir esse bitmap para a tela da impressora (canvas), o que funciona, mas descarta a única coisa em que uma impressora é excelente. Uma impressora laser moderna resolve 600 ou 1200 DPI; um bitmap rasterizado a 150 ou 300 DPI e depois esticado para caber chega sem nitidez, com bordas de texto serrilhadas e interpolação visível. O RenderLoadedPageToDC segue o melhor caminho: ele reproduz o fluxo de conteúdo da página como chamadas GDI emites diretamente no contexto de dispositivo de destino, para que o texto vetorial e a arte linear cheguem à impressora como vetores e sejam rasterizados apenas uma vez, pela própria impressora, em sua resolução nativa
Como imprimir um PDF carregado para uma impressora física no Delphi?
O HotPDF imprime um documento carregado com PrintLoadedDocument(Printer, Options), que recebe um TPrinter da VCL atribuído e um registro THPDFPrintOptions, imprime as páginas selecionadas e retorna a contagem de páginas enviadas. Defina o Printer.PrinterIndex primeiro para que um dispositivo seja escolhido, preencha um registro de opções — a função de classe THPDFPrintOptions.Default fornece valores sensatos — e chame-o uma vez. A biblioteca abre o trabalho com o Printer.BeginDoc, percorre o intervalo de páginas emitindo um Printer.NewPage entre as páginas e o fecha com o Printer.EndDoc, de modo que você nunca gerencia o ciclo de vida do trabalho de impressão manualmente
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;
A string PageRange é baseada em um e é lida da mesma forma que uma caixa de diálogo de impressão: '1,3-5' imprime a página 1 e as páginas de 3 a 5, e uma string vazia imprime o documento inteiro. O Copies mapeia diretamente para o Printer.Copies. Seja honesto consigo mesmo sobre o Collate, no entanto: como a VCL expõe a intercalação de forma inconsistente entre as versões do Delphi, o HotPDF define a contagem de cópias e deixa a intercalação a cargo do padrão do driver da impressora; portanto, quando você precisar de uma ordem de intercalação garantida, configure-a no driver por meio do TPrinterSetupDialog em vez de confiar no sinalizador para gerenciar isso
Como o DPI e o FitPage decidem a escala de impressão?
O FitPage e o DPI interagem de uma forma que vale a pena entender antes de enviar. Com o FitPage definido como True — o padrão —, o HotPDF lê o MediaBox de cada página, dimensiona-o para o Printer.PageWidth e Printer.PageHeight preservando a proporção e renderiza na escala que faz a página preencher o papel. Nesse modo, o Options.DPI é efetivamente substituído pela escala de ajuste, porque a saída deve corresponder às dimensões físicas da página da impressora. Com o FitPage definido como False, o HotPDF renderiza cada página em escala 1:1 exatamente no Options.DPI especificado, mapeando 72 unidades de PDF para pixels de dispositivo do DPI, que é o que você deseja quando a página de origem e o papel já são do mesmo tamanho e você se importa com uma resolução exata. Escolha o FitPage quando o tamanho da página de origem e o tamanho da bandeja diferirem; escolha 1:1 quando eles concluírem e você desejar um dimensionamento determinístico
Duas opções adicionadas na v2.348.0 corrigem as impressões que parecem quase corretas. Cada impressora física possui uma margem física — uma borda não imprimível que o hardware não consegue alcançar — e, por padrão, a origem da página cai dentro dela, de modo que uma página com sangria total perde uma faixa em duas bordas. Defina o IgnoreHardMargin como True e o HotPDF consultará o PHYSICALOFFSETX e o PHYSICALOFFSETY da impressora, deslocando a origem do dispositivo para cancelar esse deslocamento de modo que a origem da página seja mapeada para o canto real do papel. A segunda opção, AutoRotate, está ativa por padrão: ela lê o MediaBox de cada página e, quando uma página é mais larga do que alta, muda a impressora para paisagem para que uma página larga seja impressa sem cortes em vez de ser cortada no modo retrato. O AutoRotate é ignorado no momento em que você define a Orientation explicitamente, portanto uma escolha deliberada de orientação sempre prevalece
Como renderizar uma página PDF em qualquer contexto de dispositivo?
O RenderLoadedPageToDC(PageIndex, DC, DPI, W, H) é o primitivo sob o loop de impressão e é útil por si só. O PrintLoadedDocument o chama uma vez por página contra a tela da impressora, mas o destino pode ser qualquer HDC do Windows: um DC de memória fora da tela, a tela de um controle em um visualizador personalizado ou uma superfície de visualização de impressão. O PageIndex é baseado em zero, W e H são as unidades de dispositivo da superfície de destino, e o renderizador percorre o /Contents da página e emite chamadas GDI no seu DC. Um comportamento deliberado vale a pena conhecer: ele não desenha nenhum preenchimento de fundo. O chamador possui a superfície, portanto, se você quiser papel branco atrás da página, preencherá o DC você mesmo antes de renderizar, o que é exatamente o que permite compor uma página sobre uma tela existente quando você desejar
// Desenhe a página 1 em uma superfície de 24 bits fora da tela a 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);
// A superfície agora contém a página composta, pronta para transferência de blocos (blit) ou salvamento
finally
Surface.Free;
end;
end;
Quando você precisa apenas de um TBitmap finalizado — uma miniatura, uma exportação de imagem, uma visualização que você armazenará em cache —, use o RenderLoadedPageToBitmap, abordado no artigo complementar sobre renderizando páginas PDF em um bitmap. A diferença está em quem possui a superfície: a chamada de bitmap aloca e retorna um buffer de pixel, enquanto o RenderLoadedPageToDC desenha em um contexto de dispositivo que você já possui, que é exatamente o que a tela de uma impressora ou um manipulador de pintura fornece. Ambos compartilham o mesmo interpretador de fluxo de conteúdo e motor de glifo incorporado, de modo que o texto sai com os contornos incorporados exatos de qualquer maneira
Como colar uma página PDF no Word ou em um editor de imagens?
O RenderLoadedPageToClipboard(PageIndex, DPI, AsMetafile) coloca uma página na área de transferência do Windows, pronta para ser colada no Word, PowerPoint, em um e-mail ou em um editor de imagens. O sinalizador AsMetafile escolhe o formato, e a escolha importa mais do que parece. Passe False e o HotPDF colocará um bitmap de dispositivo de 24 bits (CF_BITMAP) renderizado no seu DPI — uma grade fixa de pixels que pode ser colada em qualquer lugar, mas fica pixelizada quando o destinatário a amplia. Passe True e ele colocará um meta-arquivo aprimorado (CF_ENHMETAFILE) no qual o texto da página e a arte vetorial viajam como comandos de desenho GDI; assim, o resultado colado permanece nítido em qualquer nível de zoom e se ajusta a qualquer tamanho que o documento de destino fornecer
// Copie a página 2 como um meta-arquivo vetorial escalável para colar no Word
Pdf.RenderLoadedPageToClipboard(1, 300, True);
// Copie a mesma página como um bitmap fixo de 300 DPI em vez disso
Pdf.RenderLoadedPageToClipboard(1, 300, False);
A regra geral é simples. Se um ser humano for colar a página em um documento e puder redimensioná-la — uma figura em um relatório, uma cláusula em um rascunho de contrato —, use the meta-arquivo, porque o texto vetorial é impresso e ampliado de forma limpa. Se o destino entender apenas dados rasterizados, ou se você desejar especificamente um instantâneo fixo em uma resolução conhecida, use o bitmap. Para extrair as palavras de uma página em vez de uma imagem delas, esse é um trabalho totalmente diferente, gerenciado pela API de extração de texto, que retorna os caracteres e suas posições em vez de uma imagem renderizada
Onde o caminho de impressão para
Tudo nesta página é exclusivo para Windows, e vale a pena dizer isso claramente. O PrintLoadedDocument, o RenderLoadedPageToDC e o RenderLoadedPageToClipboard são construídos com base no TPrinter, no modelo de contexto de dispositivo GDI, na área de transferência do Windows e nos meta-arquivos aprimorados — todos construções de Win32 e Win64. Em outras plataformas, o restante do HotPDF ainda cria, edita e lê PDFs, mas essa superfície de impressão e área de transferência apoiada pelo GDI não está disponível. O renderizador também visa o subconjunto comum de documentos de texto, caminhos e imagens, portanto, provas de design com muitos gradientes e cores gerenciadas por ICC são impressas como uma visualização fiel em vez de uma prova colorimétrica, o mesmo limite que o renderizador de bitmap carrega
Para impressão em lote de vários arquivos, carregue e imprima cada documento sucessivamente e monitore o consumo de memória: o PrintLoadedDocument renderiza uma página de cada vez, mas o próprio grafo do documento carregado permanece na memória durante todo o trabalho. Quando você estiver controlando uma fila de impressão com centenas de arquivos grandes, a streaming API de arquivo direto para fluxos de trabalho com PDFs grandes combina bem com o caminho de impressão — divida, mescle ou selecione as páginas necessárias no disco primeiro e, em seguida, carregue apenas o resultado reduzido para imprimir. É assim que o PrintLoadedDocument, o RenderLoadedPageToDC e o RenderLoadedPageToClipboard são fornecidos como parte do Componente HotPDF para Delphi e C++Builder — uma biblioteca VCL nativa sem dependências de DLL externas que cobre criação, edição, extração de texto, renderização e agora impressão de PDFs diretamente no TPrinter, em qualquer contexto de dispositivo ou na área de transferência