Artículo técnico

Representar degradados PDF en Delphi: axiales y radiales

Un PDF cuyo encabezado lleva un fondo degradado al estilo de Word o Excel, representado como imagen, solía volver con un rectángulo blanco en blanco donde debía estar la mezcla de color. El renderizador de páginas de HotPDF ahora honra el operador PDF sh (shading) para degradados axiales de tipo 2 y radiales de tipo 3: evalúa la función del sombreado a lo largo del eje del degradado y pinta la mezcla, mientras que las versiones anteriores descartaban el operador en silencio y dejaban la región del color del papel. Los dos tipos de sombreado que cubren casi todos los degradados de documentos de oficina ya están; los tipos de malla no, y este artículo es honesto sobre dónde cae esa línea

Por qué un degradado PDF se representa como una caja blanca

Un degradado PDF es un constructo vectorial, no un mapa de bits que el renderizador pueda volcar. Un diccionario de sombreado (ISO 32000-1 §8.7.4.5) describe la geometría — un eje o un par de círculos en el arreglo Coords — más una función de color, y el operador sh pinta ese sombreado sobre la región de recorte actual, el mismo modelo gráfico que HotPDF expone cuando usted dibuja rutas y rellenos en el lienzo de una página. El renderizador de páginas de HotPDF recorre el flujo de contenido operador por operador, y cualquier operador para el que no tenga una ruta de código se omite para que el resto de la página igual se represente. Antes de la versión 2.335.0, sh vivía en ese conjunto omitido: un degradado de encabezado o de página completa no aportaba nada a la salida, así que el fondo se veía blanco. El archivo nunca estuvo dañado. El renderizador sencillamente no tenía un manejador para ese único operador, y una caja blanca es exactamente el aspecto que tiene un manejador faltante

El renderizador de páginas de HotPDF en Delphi recorre el flujo de contenido operador por operador, donde el operador sh no manejado dejaba el encabezado degradado del color del papel y el pintor de sombreados ahora pinta la mezcla
Antes de la versión 2.335.0 HotPDF omitía el operador sh y dejaba la región del color del papel, y el pintor de sombreados ahora se engancha a la misma llamada RenderLoadedPageToBitmap y evalúa la mezcla a lo largo de Coords

La cadena de evaluación de funciones detrás de un sombreado

Un sombreado no se puede pintar hasta que su función se evalúa, así que esa maquinaria tuvo que llegar primero. Los sombreados axiales de tipo 2 y radiales de tipo 3 llevan ambos una /Function que mapea una posición paramétrica a lo largo del degradado hacia un color (ISO 32000-1 §7.10), y el evaluador de funciones de HotPDF resuelve el FunctionType y despacha según él. La interpolación exponencial de tipo 2 (§7.10.3) calcula C0 + t^N * (C1 - C0) con el acotamiento de Domain y Range; las funciones muestreadas de tipo 0 (§7.10.2) leen una grilla de muestras de 8, 16 o 32 bits y eligen la más cercana a través del mapa Encode, el caso tratado a fondo en nuestro recorrido por las búsquedas de color muestreadas de tipo 0; las funciones de costura de tipo 3 (§7.10.4) seleccionan una subfunción según el arreglo Bounds y descienden a ella. Las funciones de calculadora PostScript de tipo 4 (§7.10.5) no se evalúan: degradan con elegancia hacia una evaluación fallida en lugar de un color equivocado, en línea con la política conservadora que HotPDF adopta en toda la ruta de representación. Este evaluador llegó en la versión 2.334.0, una entrega antes que el operador mismo, porque el pintor de sombreados vale tanto como la función que tiene debajo

Cómo convierte HotPDF un degradado continuo en píxeles

HotPDF aproxima la mezcla continua con una serie finita de bandas de color sólido. El pintor de sombreados recorre el eje del degradado, lo divide en hasta 64 bandas — menos cuando el eje es corto en píxeles de dispositivo —, evalúa la función en la posición paramétrica de cada banda y rellena con una brocha sólida un rectángulo perpendicular al eje. El compromiso está entre la cantidad de bandas y la suavidad: más bandas siguen la mezcla más de cerca pero cuestan más rellenos, y 64 es el techo deliberado. Como la cantidad también escala con la longitud del eje en píxeles de dispositivo, la resolución importa. Representar la misma página a mayor DPI alarga el eje, así que un degradado corto gana bandas y sus franjas se suavizan hasta alcanzar el techo

El pintor de sombreados de HotPDF discretiza un degradado axial continuo en hasta 64 bandas de color sólido evaluadas a lo largo de Coords, y una representación en Delphi a mayor DPI alarga el eje de dispositivo antes del techo de 64 bandas
La mezcla continua se vuelve una serie de rectángulos sólidos perpendiculares al eje del degradado, y representar la misma página a mayor DPI gana bandas hasta que el techo suaviza las franjas
// El discretizador de sombreados usa hasta 64 bandas de color a lo largo
// del eje del degradado, pero nunca más de lo que mide ese eje en píxeles
// de dispositivo. Representar la misma página a mayor DPI alarga ese eje,
// así que un degradado corto gana bandas y el bandeado se suaviza hasta el techo de 64.
Thumb := Pdf.RenderLoadedPageToBitmap(PageIndex, 96);   // bandas más gruesas
Proof := Pdf.RenderLoadedPageToBitmap(PageIndex, 300);  // hasta 64 bandas

Representar una página con sombreados en un mapa de bits

El punto de entrada público no cambia: RenderLoadedPageToBitmap recibe un índice de página que arranca en cero y un valor de DPI, devuelve un mapa de bits de 24 bits cuya propiedad queda en manos del llamador, y entrega nil ante una falla en lugar de lanzar una excepción, así que el soporte de sombreados es transparente para el código que usted ya tiene. Una página que antes representaba su encabezado degradado en blanco ahora devuelve el mismo mapa de bits con la mezcla pintada, y no hace falta ningún cambio de API para obtenerlo. Lo único que vale la pena recordar es la propiedad del recurso: el llamador libera el mapa de bits devuelto. El pipeline completo de representación — interpretación del flujo de contenido, glifos incrustados y caché de páginas — se trata en la guía para representar páginas PDF en un mapa de bits en Delphi

var
  Pdf: THotPDF;
  Bmp: TBitmap;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('quarterly-report.pdf') > 0 then
    begin
      // Página 1 (base cero) a 150 DPI. Un encabezado relleno con degradado
      // que antes volvía en blanco ahora trae su mezcla de color.
      Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
      if Assigned(Bmp) then
      try
        Bmp.SaveToFile('page1.bmp');
      finally
        Bmp.Free;
      end;
    end;
  finally
    Pdf.Free;
  end;
end;

De la misma llamada sale una guardia de regresión barata. Represente la página, muestree un píxel donde corresponde la banda del degradado y confirme que ya no es el blanco de papel al que el renderizador solía recaer: una comprobación de una línea que atrapa un regreso silencioso al viejo comportamiento sin efecto

Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
if Assigned(Bmp) then
try
  // True cuando el operador sh pintó; False si la región recayó en blanco.
  HeaderPainted := Bmp.Canvas.Pixels[Bmp.Width div 2, 8] <> clWhite;
finally
  Bmp.Free;
end;

Lo que HotPDF no pinta: sombreados de malla y bordes de recorte

Los cuatro tipos de sombreado de malla quedan fuera del alcance, y conviene saberlo de entrada. Las mallas de triángulos Gouraud de forma libre (tipo 4), las mallas Gouraud en retícula (tipo 5), las mallas de parches Coons (tipo 6) y las mallas de parches de producto tensorial (tipo 7), definidas entre §8.7.4.5.5 y §8.7.4.5.8 de ISO 32000-1, no se representan; una página que usa alguna igual se representa, solo que esa región queda tal cual. Vale la pena declarar sin rodeos otros dos bordes. Los rectángulos de banda cubren la franja del sombreado en vez de recortarse con exactitud a la ruta de recorte actual, así que un degradado enmascarado en una forma redondeada o irregular se pinta como su franja envolvente hasta que llegue el recorte preciso de regiones en una ronda posterior. HotPDF también supone que la salida de la función es RGB o escala de grises, así que un sombreado creado en CMYK o en un espacio de color exótico se aproxima en lugar de gestionarse por color. Para los documentos que la mayoría de los equipos de Delphi y C++Builder procesa de verdad — informes, facturas, estados de cuenta y presentaciones exportadas a PDF — los tipos axial y radial cubren prácticamente todo degradado que usted encontrará, y las pruebas de diseño cargadas de mallas son el caso que conviene tratar como vista previa y no como prueba

El renderizador de páginas de HotPDF, el soporte del operador sh descrito aquí y el evaluador de funciones de tipo 0, 2 y 3 que tiene debajo vienen incluidos en el HotPDF Delphi Component para Delphi y C++Builder — una biblioteca VCL nativa sin dependencias de DLL externas, que cubre la creación, edición, extracción de texto y representación de páginas PDF en un solo paquete