Un código de barras no es una imagen con la que se decora un documento. Es una medición, y el escáner es el instrumento que la lee. Ese reencuadre decide casi todo sobre cómo debéis dibujarlo en un PDF. Las barras no llevan información por su negrura; la información vive en la relación entre los anchos de las barras y los anchos de los espacios, y un lector la recupera midiendo las transiciones mientras un láser o sensor barre la superficie. Apretad esa geometría, difuminadla o apretad sus márgenes, y produciréis algo que parece exactamente un código de barras y se escanea como una mancha. HotPDF os da dos formas de colocarlo en una página, y la diferencia entre ellas es precisamente la diferencia entre controlar esa geometría y cederla.

Qué puede codificar HotPDF
HotPDF dibuja simbologías lineales (unidimensionales), y el conjunto es más amplio de lo que necesitan la mayoría de los proyectos. La enumeración THPDFBarcodeType cubre la familia Code 2 of 5 en sus formas intercalada, industrial y matricial; Code 39 y su variante extendida; los tres subconjuntos A, B y C de Code 128; Code 93 simple y extendido; MSI; PostNet; Codabar; el grupo retail UPC y EAN, a saber EAN-8, EAN-13, UPC-A, los comprimidos UPC-E0 y UPC-E1, y los suplementos UPC de 2 y 5 dígitos; y los subconjuntos GS1-128 (EAN-128). Eso es suficiente para cubrir etiquetas de cadena de suministro, punto de venta en tiendas y los antiguos códigos industriales que siguen activos en almacenes.
Lo que no dibuja es la familia bidimensional. No hay QR, Data Matrix ni PDF417 aquí. Esos codifican bytes en una cuadrícula con su propia matemática de corrección de errores, y si un requisito nombra uno de ellos, esta no es la herramienta adecuada y deberíais saberlo antes de construir sobre ella en lugar de después. Para los códigos unidimensionales la pregunta práctica es más concreta: qué simbología acepta los datos que realmente tenéis, porque las codificaciones no son intercambiables.
Las restricciones de datos son reales y muerden en el momento de la generación. Las variantes de Code 2 of 5 y MSI solo aceptan dígitos. Code 39 lleva letras mayúsculas, dígitos y un puñado de signos de puntuación; si necesitáis minúsculas o todo el rango ASCII, eso es Code 39 Extended o un subconjunto de Code 128. Code 128C empaqueta dos dígitos en cada símbolo para mayor densidad, por lo que requiere una cadena numérica de longitud par y nada más. EAN-13 espera doce dígitos y calcula el decimotercero como control; EAN-8 espera siete y calcula el octavo; UPC-A toma doce. Pasad a una simbología datos que no puede representar y no obtendréis una excepción útil, sino un código de barras que codifica basura, lo cual es peor, porque tiene buen aspecto hasta que alguien lo escanea en una caja.
Dos caminos de dibujo, dos niveles de control
El método al que recurrir en producción es DrawBarcode, en el objeto de página. Toma la simbología, una posición, una altura y un parámetro que importa más que el resto: MUnit, el ancho de módulo. El módulo es el ancho de la barra más estrecha, el átomo del que todas las demás medidas del código son múltiplos, y se expresa aquí en puntos. Todo lo relativo a si el resultado impreso se escanea se remonta a ese único entero.
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'label.pdf';
Pdf.BeginDoc;
// BCType, X, Y, Height, MUnit (module width in points), angle,
// data, UseCheckSum, bar color, background color.
Pdf.CurrentPage.DrawBarcode(
bcCodeEAN13, // symbology
72, 680, // X, Y in points from the bottom-left
60, // bar height
1, // MUnit: 1pt narrowest bar
0, // no rotation
'123456789012', // 12 digits; the 13th is the check
True, // append the modulo-10 check digit
clBlack, clWhite); // bars black, background white
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Dos argumentos merecen un examen más detenido. UseCheckSum añade el dígito de control módulo 10 que espera la simbología, y para los códigos de venta al por menor casi siempre queréis que sea True; desactivadlo solo cuando vuestros datos ya lleven un dígito de control precalculado, o se obtendrá un dígito duplicado. El color de las barras y el del fondo son los dos últimos parámetros, y la tentación de ser creativos ahí es una trampa que se analiza más adelante. Fijad también el origen de coordenadas: como cualquier otra llamada de dibujo en HotPDF, X e Y se miden desde la esquina inferior izquierda de la página en puntos, con Y creciendo hacia arriba, la misma convención que el ejemplo Hello World desarrolla.
El segundo camino es DirectDrawBarcode, que recibe los datos y un cuadro delimitador, X, Y, Width, Height, y escala el patrón de barras para rellenar ese ancho. Es cómodo para distribuir códigos en una cuadrícula porque se nombra el área ocupada y el método ajusta las barras a ella. Esa comodidad es también su riesgo. Al especificar un ancho, ya no se está fijando el tamaño del módulo; el método divide el espacio disponible entre el número de barras que necesitan los datos, y la barra más estrecha resulta de esa división. Si se pide una cadena Code 128 densa dentro de un cuadro demasiado estrecho, los módulos se encogerán por debajo de lo que cualquier escáner puede resolver, sin ninguna advertencia. Para todo lo que deba escanearse de forma fiable, preferid DrawBarcode y estableced MUnit de forma deliberada. Reservad DirectDrawBarcode para previsualizaciones y para disposiciones en las que hayáis comprobado que las barras resultantes siguen siendo legibles.
El ancho de módulo es una decisión de resolución
Esta es la aritmética que determina si vuestra etiqueta funciona. Tanto un escáner láser como una cámara tienen una característica mínima que pueden distinguir, y la barra estrecha debe quedar cómodamente por encima de ella tras la impresión. El suelo ampliamente citado para los códigos lineales de uso general es una barra estrecha de 13 milésimas de pulgada, unos 0,33 mm, y muchas guías de distribución e industria lo tratan como mínimo en lugar de objetivo. Traducido a unidades PDF: un punto es 1/72 de pulgada, aproximadamente 0,353 mm, de modo que un módulo de un punto se sitúa justo en ese suelo. Por eso MUnit := 1 es el valor más pequeño que debéis usar para un código destinado a un escáner real, y por eso duplicarlo a 2 proporciona margen que cuesta casi nada en una etiqueta con espacio de sobra.
Conectad esto con la resolución de salida, porque el módulo también debe sobrevivir a la impresora. En una impresora láser de 300 PPP, un punto de dispositivo es 1/300 de pulgada, por lo que un módulo de un punto mide unos cuatro puntos de ancho. Cuatro puntos apenas bastan para reproducir un borde limpio; la dispersión del tóner y un ligero error de registro lo reducen, y la barra que medía un punto en vuestro PDF se imprime más gruesa o más delgada de lo que permite la especificación. Aumentad el módulo a 2 puntos y tendréis ocho puntos con los que trabajar, lo que absorbe ese ruido. La regla que conviene interiorizar: el ancho de módulo que se establece en puntos debe corresponderse con un número entero y cómodo de puntos de dispositivo a la resolución de impresión real, no a la que ojalá tuviérais. Un código que se escanea perfectamente en pantalla y falla en la impresora del almacén casi siempre ha fallado esta comprobación.
La zona de silencio es parte del símbolo
La razón más habitual por la que un código de barras correctamente codificado no se escanea es la zona de silencio, el margen en blanco a cada lado de las barras. Los escáneres utilizan ese espacio vacío para encontrar dónde comienza y termina el código; sin él, el lector no puede distinguir la primera barra de lo que haya junto a ella en la página. Las normas son precisas. La mayoría de las simbologías lineales requieren una zona de silencio de al menos diez veces el ancho del módulo a cada lado, y los códigos minoristas UPC y EAN exigen nueve módulos a la izquierda y siete a la derecha. Con un módulo de un punto, eso son aproximadamente diez puntos, alrededor de un séptimo de pulgada, de espacio blanco garantizado flanqueando las barras.
HotPDF dibuja las barras y nada más. No reserva la zona de silencio por vosotros, lo que significa que la responsabilidad es vuestra y es fácil olvidarlo. El modo de fallo es sutil: colocáis un código de barras pegado al borde de una celda de tabla, o dejáis que el diseño de página apriete un logotipo junto a él, y el código que pasó todas las pruebas en una página en blanco deja de escanearse en cuanto aparece dentro de un documento real. Reservad el margen explícitamente. Antes de llamar a DrawBarcode, dejad al menos diez anchos de módulo de espacio libre a ambos lados, y tratad cualquier gráfico, regla o texto que se introduzca en esa banda como un defecto, no como una elección estética.
Color, contraste y la línea legible por humanos
Los colores de barras y fondo existen para que podáis ajustaros a una paleta corporativa, y son la forma más rápida de romper un código que funciona. Los escáneres leen el contraste, clásicamente con luz roja, y esperan barras oscuras sobre un campo claro. Negro sobre blanco es la única combinación a la que debéis recurrir sin probar. El azul oscuro o el verde oscuro sobre blanco pueden pasar; cualquier cosa con bajo contraste de luminancia, y en particular las barras rojas, que un escáner de luz roja ve como fondo, no lo hará. Si un diseñador pide códigos de barras en color, la respuesta honesta es que las barras permanecen negras y el color va a otro lugar de la etiqueta.
El camino de DrawBarcode también puede representar el texto legible por humanos debajo de las barras, los dígitos que un operario introduce cuando falla el escaneado. Ese texto es un mecanismo de reserva, no decoración, así que cuando coloquéis vuestro propio pie de texto, mantened la zona de silencio libre; una etiqueta de la simbología apretada en el margen lateral elimina el mismo espacio en blanco del que depende el escáner. Los campos del ejemplo aquí, incluido TextOut para cualquier etiqueta alrededor, son las mismas llamadas de dibujo tratadas en la guía de salida de informes, que es el recurso adecuado cuando el código de barras es un elemento dentro de una página compuesta más amplia.
Un breve hábito de verificación
Las barras vectoriales son una ventaja que merece mencionarse. Como DrawBarcode escribe el código como operadores de dibujo PDF en lugar de una imagen rasterizada, las barras se mantienen nítidas a cualquier nivel de zoom y el fichero no tiene resolución propia; la única que importa es la de la impresora. Eso no os exime de realizar pruebas, simplemente significa que la prueba debe hacerse en papel. Generad una muestra, imprimidla en el dispositivo de menor resolución que vuestros códigos encontrarán realmente, y escanead con el mismo tipo de lector que usan vuestros usuarios, no con el escáner de alta gama de vuestro escritorio. Comprobad las zonas de silencio con una regla sobre la impresión, confirmad que el ancho de módulo ha sobrevivido el paso de puntos a puntos de dispositivo, y verificad que el valor decodificado coincide con lo que codificasteis, dígito de control incluido. Cinco minutos con un escáner real detecta todos los fallos descritos anteriormente, y los detecta antes de que lo haga un palé de mercancía mal etiquetada.
Los métodos DrawBarcode y DirectDrawBarcode mostrados aquí forman parte del HotPDF Component para Delphi y C++Builder.