Cada cadena visible en un documento de HotPDF llega a través de una sola llamada: TextOut(X, Y, angle, Text). El ejemplo del Hola Mundo la usa en su forma más simple, la fuente configurada una vez y cuatro argumentos con valores predeterminados sensatos. Pasada esa primera página, los mismos cuatro argumentos cargan todo el peso del diseño. El tercer argumento rota el bloque. La fuente establecida justo antes decide el tamaño y el estilo. Y el par X, Y, medido desde la esquina de la página en puntos, es lo único que se interpone entre un reporte limpio y un texto que se superpone, se recorta o se desvía una línea más abajo en la impresora de otra persona. Aquí es donde TextOut demuestra su valor, y donde los valores predeterminados dejan de ser suficientes
Vale la pena fijar la firma en la mente antes que nada: X e Y son Single en puntos, angle es un Extended en grados, y Text es un WideString, por lo que Unicode pasa de forma directa sin una llamada por separado. Una segunda sobrecarga toma un PWORD más una longitud para cuando usted ya posee los códigos de los glifos, pero para las cadenas ordinarias la forma WideString es la que va a utilizar
El tamaño y el estilo provienen de SetFont, no de TextOut
TextOut no tiene parámetro de tamaño. El tamaño, el peso, la inclinación, todo esto reside en la llamada SetFont que precede al bloque, y se mantiene vigente hasta que el siguiente SetFont lo reemplace. Ese es el único dato que explica la mayor parte de la confusión del primer día: una línea sale en negrita porque tres llamadas antes algo estableció [fsBold] y nada lo limpió
Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report'); // 24pt regular
Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue'); // 12pt bold
Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands'); // 11pt italic
Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, ' +18.4% YoY'); // styles combine
El segundo argumento es un conjunto TFontStyles, de modo que [fsBold, fsItalic] es negrita cursiva y [] es normal. El tamaño está en puntos, la misma unidad que las coordenadas, lo que facilita el razonamiento sobre el espaciado vertical: una línea de 12 puntos necesita aproximadamente entre 14 y 16 puntos de paso vertical para respirar, por lo que reducir Y en 14 por línea es un interlineado inicial razonable. No hay un avance de línea automático. Usted calcula cada línea base por sí mismo, lo cual es tedioso para un párrafo pero exacto para un formulario, donde cada campo se encuentra en una coordenada fija
Dos notas prácticas sobre el nombre de la fuente. Se resuelve de acuerdo con las fuentes instaladas en el equipo de compilación, y lo que sea que el sistema operativo devuelva es lo que se incrusta, por lo que no se garantiza que un nombre que se resuelva en su escritorio y un nombre que se resuelva en un servidor de compilación sean la misma tipografía. Y la fuente tiene que cubrir las escrituras en la cadena. Un bloque de texto cirílico o CJK bajo un tipo de letra exclusivamente latino se procesa como cuadros de glifos faltantes sin ningún error, lo cual es la razón por la que la página de Hola Mundo recurre a un tipo de letra Unicode amplio cuando mezcla idiomas
El argumento de ángulo rota alrededor del ancla
El tercer argumento es el que la mayoría del código deja en cero por siempre. Si pasa un valor distinto de cero, el bloque rota en sentido antihorario sobre su propia ancla (X, Y), la parte inferior izquierda del texto, por esa cantidad de grados. El ancla en sí no se mueve, de modo que la misma coordenada que colocó una etiqueta horizontal ubica a su gemela rotada; solo cambia la dirección en la que marchan los glifos
Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);
// A vertical axis label down the left margin: 90 degrees reads bottom-to-top.
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');
// A diagonal DRAFT watermark across the page body.
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');
// Column headers tilted 60 degrees so long labels fit a narrow table.
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');
Noventa grados es el caso común, una etiqueta que sube por el lado de un gráfico o un título de lomo. Cuarenta y cinco grados maneja encabezados de columnas inclinados, el truco que permite que una etiqueta ancha se ubique sobre una columna estrecha sin derramarse hacia sus vecinos. La rotación no cambia cómo se interpreta el ancla, lo que hace tropezar a las personas: un bloque de 90 grados aún comienza en (X, Y) y crece hacia arriba desde ahí, de modo que para centrar una etiqueta rotada, usted ajusta el ancla, no el ángulo. Cuando varios bloques rotados comparten una línea base, deles la misma Y y dé saltos en X, exactamente como saltaría en Y para líneas horizontales apiladas
Ubicación de coordenadas sin adivinar
Las coordenadas son la parte que sobrevive a la revisión o falla silenciosamente. HotPDF mide desde la esquina inferior izquierda de la página, con Y creciendo hacia arriba, en puntos a 72 por pulgada. Una página tamaño carta (US Letter) mide 612 por 792 puntos; A4 mide 595 por 842. Un margen superior de una pulgada en tamaño carta coloca su primera línea base cerca de Y = 792 menos 72 menos el tamaño de la fuente, no en un número pequeño cerca de la parte superior. Cualquiera que venga de coordenadas de pantalla, donde Y crece hacia abajo desde cero, escribe la primera línea fuera del borde inferior y pasa diez minutos preguntándose a dónde fue a parar
Trate el diseño como aritmética contra anclas con nombre en lugar de una columna de números mágicos. Un margen izquierdo, una línea base móvil que usted decrementa por línea y un interlineado fijo convierten un bloque de etiquetas en un bucle corto en lugar de un muro de literales:
const
LeftMargin = 72; // 1 inch in
TopBaseline = 720; // first line, ~1 inch down on Letter
Leading = 16; // vertical step between lines
var
Y: Single;
Line: string;
begin
Pdf.CurrentPage.SetFont('Arial', [], 11);
Y := TopBaseline;
for Line in ReportLines do
begin
Pdf.CurrentPage.TextOut(LeftMargin, Y, 0, Line);
Y := Y - Leading;
if Y < 72 then // bottom margin reached
begin
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 11); // font resets on a new page
Y := TopBaseline;
end;
end;
end;
El protector contra saltos de página es la línea que todo el mundo olvida primero y el campo que golpea más duro. No hay diseño de flujo debajo de TextOut. Si decrementa más allá del margen inferior, el texto sigue dibujándose en el margen exterior, fuera de la página, hacia la nada, sin ninguna advertencia. Por lo tanto, usted vigila la Y por sí mismo, llama a AddPage cuando cruza el piso y restablece la línea base. El SetFont después de AddPage no es un relleno opcional: la fuente actual no sobrevive a un salto de página, y el primer bloque en la nueva página sale en el tipo de letra predeterminado del visor si lo omite
Espaciado de caracteres y palabras para ajuste y alineación
En ocasiones, una cadena es correcta pero del ancho incorrecto: un encabezado que tiene que abarcar una regla fija, un código que debe leerse con dígitos más holgados, una columna que necesita que sus valores se ajusten para alinearse. PDF cuenta con dos operadores de estado de texto para esto, el espaciado de caracteres (Tc, espacio adicional agregado después de cada glifo) y el espaciado de palabras (Tw, espacio adicional agregado en cada carácter de espacio), y ambos se expresan en unidades de espacio de texto sin escalar, de manera efectiva en puntos al tamaño de fuente actual. Son estados, no argumentos para TextOut, así que los configura, dibuja y los restablece
// Letter-space a short heading so it stretches across a rule.
Pdf.CurrentPage.SetCharacterSpacing(4);
Pdf.CurrentPage.SetFont('Arial', [fsBold], 14);
Pdf.CurrentPage.TextOut(72, 740, 0, 'S U M M A R Y');
Pdf.CurrentPage.SetCharacterSpacing(0); // reset before normal body text
// Open up the gaps between words on a single wide line.
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name Department Extension');
Pdf.CurrentPage.SetWordSpacing(0);
El espaciado de palabras solo actúa sobre el carácter de espacio (código 32), lo cual tiene una consecuencia que vale la pena conocer: no hace nada dentro de un bloque CJK que no tiene espacios ASCII, e interactúa de forma extraña con el texto codificado como índices de glifos en lugar de bytes. Para la salida tabular latina es la manera barata de ampliar los espacios sin volver a escribir la cadena. El espaciado de caracteres es la mejor herramienta para un encabezado que debe alcanzar un ancho objetivo, ya que distribuye el ajuste de manera uniforme a través de cada glifo en lugar de acumularlo en los espacios
El restablecimiento es toda la disciplina. El espaciado, al igual que la fuente, es parte del estado de dibujo de la página y el estado persiste hasta que usted lo cambia. Si le da espaciado de letras a un encabezado y olvida ponerlo en cero, cada párrafo a continuación hereda el estiramiento, lo que se lee como una incorrección sutil y difícil de ubicar que sobrevive a una lectura rápida y falla en una revisión cuidadosa. El hábito confiable es establecer un valor de espaciado, dibujar el bloque que lo necesita y restablecerlo a cero en la siguiente línea, para que ningún código posterior tenga que saber lo que hizo una sección anterior
Comprobación de la salida donde realmente se rompe
El diseño de texto falla en la segunda máquina, no en la primera, por lo que las comprobaciones que importan suceden lejos de su escritorio. Abra el archivo generado en un sistema sin la fuente de desarrollador instalada y confirme que los tipos de letra incrustados todavía se renderizan, incluidos el latín acentuado, cualquier escritura no latina y la puntuación, en un solo paso en lugar de hacer comprobaciones aleatorias de los caracteres fáciles. Seleccione y copie unas pocas líneas para confirmar que el texto es texto real y no contornos, lo cual importa en el momento en que la búsqueda o la extracción están en el alcance. Alimente el diseño con datos representativos, la etiqueta alemana más larga y el número más ancho, no con un marcador de posición ordenado, porque el bloque que desborda un campo siempre es el que usted no ingresó a mano. Y si la página tiene que aterrizar en un formulario preimpreso, imprima o rasterice una muestra y colóquela contra el original; un desplazamiento de línea base de un cuarto de milímetro es invisible en la pantalla y obvio en papel
Si aún no ha escrito una sola página, comience con el ejemplo Hola Mundo de HotPDF, que configura el documento, la fuente y el sistema de coordenadas inferior izquierdo del cual depende todo lo anterior. Las llamadas TextOut, SetFont y de espaciado que se muestran aquí son parte del Componente HotPDF para Delphi y C++Builder