HotPDF imprime un PDF cargado en una impresora física, en cualquier contexto de dispositivo de Windows o en el portapapeles a través de tres llamadas: PrintLoadedDocument maneja un TPrinter de VCL, RenderLoadedPageToDC dibuja una página directamente en cualquier HDC y RenderLoadedPageToClipboard copia una página como un mapa de bits o un metarchivo vectorial. HotPDF es un componente PDF VCL nativo para Delphi y C++Builder, y añadió esta ruta de impresión de primera clase en la versión 2.331.0, perfeccionándola en la 2.348.0, para que ya no tenga que programar manualmente un bucle de TPrinter alrededor de un renderizador de mapas de bits. Las tres llamadas dibujan el contenido vectorial de la página directamente donde corresponde, por lo que la impresión se mantiene tan nítida como la impresora pueda renderizarla
Una página PDF es un programa de operadores de dibujo vectorial —rutas, texto e imágenes ejecutadas según el modelo de gráficos ISO 32000-1— no una cuadrícula de píxeles. La forma obvia de imprimir una es rasterizar la página a un mapa de bits y transferir (blit) ese mapa de bits al lienzo de la impresora, y funciona, pero descarta lo único para lo que sirve una impresora. Una impresora láser moderna resuelve 600 o 1200 DPI; un mapa de bits rasterizado a 150 o 300 DPI y luego estirado para encajar llega difuminado, con bordes de texto dentados e interpolación visible. RenderLoadedPageToDC toma un camino mejor: reproduce el flujo de contenido de la página como llamadas GDI emitidas directamente en el contexto del dispositivo de destino, por lo que el texto vectorial y el arte lineal llegan a la impresora como vectores y se rasterizan una sola vez, por la impresora, a su propia resolución
¿Cómo imprimir un PDF cargado en una impresora física en Delphi?
HotPDF imprime un documento cargado con PrintLoadedDocument(Printer, Options), que toma un TPrinter de VCL asignado y un registro THPDFPrintOptions, imprime las páginas seleccionadas y devuelve el recuento de páginas enviadas. Configure primero Printer.PrinterIndex para seleccionar un dispositivo, rellene un registro de opciones —la función de clase THPDFPrintOptions.Default le da valores razonables— y llámelo una vez. La biblioteca abre el trabajo con Printer.BeginDoc, recorre el rango de páginas emitiendo un Printer.NewPage entre páginas y lo cierra con Printer.EndDoc, por lo que nunca tendrá que gestionar el ciclo de vida del trabajo de impresión a mano
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;
La cadena PageRange se basa en uno y se lee de la misma manera que un cuadro de diálogo de impresión: '1,3-5' imprime la página 1 y las páginas de la 3 a la 5, y una cadena vacía imprime todo el documento. Copies se asigna directamente a Printer.Copies. Sea honesto consigo mismo sobre Collate (colación), sin embargo: debido a que VCL expone la colación de manera inconsistente entre las versiones de Delphi, HotPDF establece el recuento de copias y deja la colación al valor predeterminado del controlador de la impresora, por lo que cuando necesite un orden de colación garantizado, configúrelo en el controlador a través de TPrinterSetupDialog en lugar de confiar en que la bandera lo asuma
¿Cómo deciden la escala de impresión DPI y FitPage?
FitPage y DPI interactúan de una manera que vale la pena entender antes de realizar entregas. Con FitPage en True —el valor predeterminado— HotPDF lee el MediaBox de cada página, lo escala a Printer.PageWidth y Printer.PageHeight conservando la relación de aspecto, y lo renderiza a la escala que hace que la página llene el papel. En ese modo, la escala de ajuste invalida efectivamente a Options.DPI, porque la salida debe coincidir con las dimensiones físicas de la página de la impresora. Con FitPage en False, HotPDF renderiza cada página 1:1 exactamente al Options.DPI, asignando 72 unidades PDF a los píxeles de dispositivo de DPI, que es lo que desea cuando la página de origen y el papel ya son del mismo tamaño y le importa tener una resolución exacta. Recurra a FitPage cuando el tamaño de la página de origen y el tamaño de la bandeja difieran; recurra a 1:1 cuando coincidan y desee un escalado determinista
Dos opciones añadidas en la versión 2.348.0 corrigen las impresiones que se ven casi bien. Cada impresora física tiene un margen físico (hard margin) —un borde no imprimible al que el hardware no puede llegar— y por defecto el origen de la página cae dentro de este, por lo que una página a sangre completa pierde una franja en dos bordes. Establezca IgnoreHardMargin en True y HotPDF consultará los valores de PHYSICALOFFSETX and PHYSICALOFFSETY de la impresora, y luego desplazará el origen del dispositivo para cancelar ese desfase para que el origen de la página se asigne a la esquina real del papel. La segunda opción, AutoRotate, está activada de forma predeterminada: lee el MediaBox de cada página y, cuando una página es más ancha que alta, cambia la orientación de la impresora a horizontal para que la página ancha se imprima sin recortarse en lugar de recortarse a vertical. AutoRotate se desactiva en el momento en que se establece la Orientation explícitamente, por lo que una elección de orientación deliberada siempre gana
¿Cómo renderizar una página PDF en cualquier contexto de dispositivo?
RenderLoadedPageToDC(PageIndex, DC, DPI, W, H) es la primitiva debajo del bucle de impresión, y es útil por sí sola. PrintLoadedDocument la llama una vez por página contra el lienzo de la impresora, pero el destino puede ser cualquier HDC de Windows: un DC de memoria fuera de pantalla, el lienzo de un control en un visor personalizado o una superficie de vista previa de impresión. PageIndex se basa en cero, W y H son las unidades de dispositivo de la superficie de destino, y el renderizador recorre el /Contents de la página y emite llamadas GDI en su DC. Vale la pena conocer un comportamiento deliberado: no dibuja ningún relleno de fondo. El llamador es propietario de la superficie, por lo que si desea papel blanco detrás de la página, usted mismo llena el DC antes de renderizar, que es exactamente lo que le permite componer una página sobre un lienzo existente cuando lo desee
// 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;
Cuando solo necesite un TBitmap finalizado —una miniatura, una exportación de imagen, una vista previa que almacenará en caché— recurra en su lugar a RenderLoadedPageToBitmap, cubierto en el artículo complementario sobre renderizado de páginas PDF a un mapa de bits. La diferencia es quién posee la superficie: la llamada de mapa de bits asigna y devuelve un búfer de píxeles, mientras que RenderLoadedPageToDC dibuja en un contexto de dispositivo que usted ya posee, que es exactamente lo que le entrega el lienzo de una impresora o un controlador de pintura. Ambos comparten el mismo intérprete de flujo de contenido y el motor de glifos incrustados, por lo que el texto sale con los contornos incrustados exactos de cualquier manera
¿Cómo pegar una página PDF en Word o en un editor de imágenes?
¿Cómo pegar una página PDF en Word o en un editor de imágenes?
RenderLoadedPageToClipboard(PageIndex, DPI, AsMetafile) coloca una página en el portapapeles de Windows, lista para pegarse en Word, PowerPoint, un correo electrónico o un editor de imágenes. La bandera AsMetafile elige el formato, y la elección importa más de lo que parece. Pase False y HotPDF colocará un mapa de bits de dispositivo de 24 bits (CF_BITMAP) renderizado al DPI indicado —una cuadrícula fija de píxeles que se pega en cualquier lugar pero que se pixela cuando el receptor la amplía. Pase True y colocará un metarchivo mejorado (CF_ENHMETAFILE) en el que el texto y el arte vectorial de la página viajan como comandos de dibujo GDI, por lo que el resultado pegado se mantiene nítido con cualquier zoom y se adapta a cualquier tamaño que le dé el documento de destino
// 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);
La regla general es simple. Si una persona va a pegar la página en un documento y podría cambiar su tamaño —una figura en un informe, una cláusula introducida en el borrador de un contrato—, use el metarchivo, porque el texto vectorial se imprime y amplía de forma limpia. Si el destino solo comprende datos rasterizados, o si desea específicamente una instantánea fija a una resolución conocida, use el mapa de bits. Para extraer las palabras de una página en lugar de una imagen de estas, ese es un trabajo completamente diferente, manejado por la API de extracción de texto, que devuelve los caracteres y sus posiciones en lugar de una imagen renderizada
Dónde se detiene la ruta de impresión
Todo en esta página es exclusivo para Windows, y vale la pena decirlo claramente. PrintLoadedDocument, RenderLoadedPageToDC y RenderLoadedPageToClipboard se basan en TPrinter, el modelo de contexto de dispositivo GDI, el portapapeles de Windows y los metarchivos mejorados —todos ellos constructos Win32 y Win64. En otras plataformas de destino, el resto de HotPDF sigue creando, editando y leyendo PDF, pero esta superficie de impresión y portapapeles respaldada por GDI no está disponible. El renderizador también se enfoca en el subconjunto de documentos común de texto, rutas e imágenes, por lo que las pruebas de diseño con muchos degradados y el color gestionado por ICC se imprimen como una vista previa fiel en lugar de una prueba colorimétrica, el mismo límite que lleva el renderizador de mapas de bits
Para la impresión por lotes de many archivos, cargue e imprima cada documento a su vez y vigile el consumo de memoria: PrintLoadedDocument renderiza una página a la vez, pero el grafo del documento cargado en sí reside en la memoria durante todo el trabajo. Cuando maneje una cola de impresión de cientos de archivos grandes, la API de transmisión Direct File API para flujos de trabajo de PDF grandes se combina bien con la ruta de impresión —divida, combine o seleccione las páginas que necesita en el disco primero, y luego cargue solo el resultado liviano para imprimir. Así es como PrintLoadedDocument, RenderLoadedPageToDC y RenderLoadedPageToClipboard se distribuyen como parte del HotPDF Component para Delphi and C++Builder, junto con el modelo de contenido completo y la referencia GDI