PDFlibPas hace fluir un pasaje retenido a través de una a 64 columnas de igual ancho con DrawTextFlowColumns, y corta sus líneas con guionado acotado y sensible al idioma una vez que usted llama a SetTextFlowLanguage y SetTextFlowHyphenation. Se soportan nueve idiomas, y el idioma puede heredarse del valor /Lang del Catalog del documento en lugar de fijarse por cada flujo
Ambas funciones existen por la misma razón: una columna angosta es donde el salto de línea ingenuo deja de parecer tipografía y empieza a parecer un reporte de errores
¿Por qué el texto justificado se desmorona en columnas angostas?
Porque la justificación distribuye el espacio sobrante en los huecos entre palabras de una línea, y la cantidad sobrante depende de lo que quepa. En una medida ancha, el sobrante es pequeño y el ojo nunca lo nota. Reduzca el ancho a la mitad y una sola palabra larga que no cabe se empuja a la línea siguiente, dejando que sus predecesoras absorban todo ese espacio. Tres líneas así en secuencia producen los canales blancos verticales que los tipógrafos llaman ríos, y que los lectores experimentan como texto difícil de seguir sin saber por qué
El guionado corrige la causa en lugar del síntoma, al permitir un corte dentro de la palabra. Los compuestos del alemán y el holandés hacen esto innegociable: un sustantivo de 24 caracteres en una columna de 60 milímetros no tiene buen resultado sin un punto de corte. El inglés tolera mejor la ausencia, razón por la cual los productos centrados en inglés a menudo distribuyen código de diseño que falla la primera vez que lo ejecuta un cliente alemán
¿Qué idiomas, y de dónde viene el idioma?
El guionado cubre inglés, alemán, holandés, francés, español, italiano, portugués, ruso y turco. Fíjelo explícitamente por flujo con SetTextFlowLanguage, o déjelo heredarse de la entrada /Lang del Catalog del documento, que es el valor que ya lleva un documento etiquetado y accesible
Vale la pena usar esa herencia en lugar de sobrescribirla. Un documento que declara su idioma en el Catalog le está diciendo el mismo hecho, desde un solo lugar, a los lectores de pantalla, a los indexadores de búsqueda y al guionado, y un solo lugar es donde debe vivir un hecho. Si usted ya está produciendo salida etiquetada como se describe en etiquetado automático para PDF accesibles, la entrada de idioma ya está fijada y el flujo simplemente puede seguirla
var
Lib: TPDFlib;
Flow, Drawn: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.SetOrigin(1);
Lib.AddTrueTypeFont('Georgia', 1);
Lib.SetTextSize(10.5);
Flow := Lib.NewTextFlow(ArticleBody);
try
Lib.SetTextFlowLanguage(Flow, 'de');
// Activar, al menos 3 caracteres antes del corte, 3 después
Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
Lib.SetTextFlowMinLines(Flow, 2); // nunca dejar una sola línea varada
repeat
// Tres columnas en una región de 480 pt, canaletas de 18 pt, equilibrado
Drawn := Lib.DrawTextFlowColumns(Flow, 72, 720, 480, 620, 3, 18, 1);
if (Drawn = 0) or (Lib.TextFlowFinished(Flow) = 1) then
Break;
Lib.NewPage;
until False;
finally
Lib.ReleaseTextFlow(Flow);
end;
Lib.SaveToFile('newsletter.pdf');
finally
Lib.Free;
end;
end;
MinPrefix y MinSuffix son tipografía, no validación
Los dos enteros después del indicador de activación fijan el número mínimo de caracteres que deben permanecer antes y después de un corte. Tres y tres es un valor predeterminado conservador que la mayoría de los estilos de casa aceptan. Dos y dos produce más oportunidades de corte y resultados notablemente más feos, porque un fragmento de dos letras colgando al final de una línea se lee como un error de tipeo
Suba los mínimos cuando el tamaño de tipo sea grande, donde cada fragmento es visualmente prominente, y bájelos solo cuando la columna sea genuinamente angosta y usted haya decidido que una medida ajustada importa más que una limpia. Esta es una decisión de estilo de casa más que una decisión técnica, que es exactamente por qué es un parámetro en lugar de una constante
¿Qué significa realmente "equilibrado" aquí?
El parámetro Balance cambia el comportamiento solo al final de un pasaje. Con el equilibrado activado, las columnas se acortan a un número exacto e igual de líneas cuando todo lo que queda cabe dentro de la región, lo cual es lo que evita que una página final muestre dos columnas completas y una tercera con una sola línea solitaria. Cuando el pasaje no cabe, cada columna conserva su altura completa, así que la página lleva tanto texto como puede, y el resto continúa en la página siguiente
Esa asimetría es el valor predeterminado correcto para documentos continuos. Equilibrar en medio de un artículo que fluye desperdiciaría espacio vertical en cada página por un efecto cosmético que nadie ve, ya que las columnas están completas de todos modos. Equilibrar al final es donde el ojo realmente lo nota, y ahí es precisamente donde se aplica
El salto de línea mide palabras completas
El algoritmo de corte mide palabras completas en lugar de acumular anchos de carácter, y reserva una búsqueda acotada para tokens sobredimensionados que no caben en una línea en absoluto, como una URL o un número de cuenta. Eso mantiene rápido el caso común y acotado el caso patológico, en lugar de lo contrario
Los guiones discrecionales suaves y los guiones automáticos se renderizan solo cuando el corte que marcan es el corte que se elige. Esto suena obvio y es un defecto clásico: una implementación ingenua escribe el carácter de guion mientras mide, y si el corte se mueve, el guion se queda atrás en medio de una línea. Nada luce más como un motor de texto roto que un guion perdido dentro de una palabra
var
Lib: TPDFlib;
Flow, Needed: Integer;
begin
// Decidir el diseño antes de dibujar cualquier cosa
Flow := Lib.NewTextFlow(ArticleBody);
try
Lib.SetTextFlowLanguage(Flow, 'fr');
Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
// Líneas que el resto del pasaje necesita a un ancho de columna
Needed := Lib.MeasureTextFlow(Flow, 148);
if Needed > 3 * LinesPerColumn then
UseTwoPageSpread
else
UseSinglePage;
Lib.DrawTextFlowColumns(Flow, 72, 720, 480, 620, 3, 18, 1);
if Lib.TextFlowFinished(Flow) <> 1 then
CarryOver(Lib.GetTextFlowRemaining(Flow));
finally
Lib.ReleaseTextFlow(Flow);
end;
end;
Mantenga idéntica la configuración de fuente entre cajas
Una regla gobierna todo diseño basado en flujo y vale la pena decirla sin rodeos: DrawTextFlow, DrawTextFlowColumns y MeasureTextFlow cortan líneas usando la fuente seleccionada en el momento en que se llaman. Cambie la fuente o el tamaño entre dos cajas del mismo flujo, o inicie una página nueva sin volver a seleccionar una, y la segunda caja corta las líneas de forma distinta a lo que midió la primera
El síntoma es exasperante precisamente porque parece intermitente: texto que cabe en la página uno se desborda en la página dos, o un conteo de líneas medido no coincide con lo que se dibujó. Seleccione la fuente una vez antes del bucle, vuelva a seleccionarla después de cada NewPage, y el flujo se comporta bien. Cuando aparecen escrituras mixtas en el mismo pasaje, la resolución descrita en respaldo automático de fuentes para texto CJK y emoji aplica tanto a la medición como al dibujo, así que los anchos se mantienen consistentes también a través de las corridas de respaldo
Para diseños de reporte donde el flujo es un elemento entre encabezados, pies de página y bloques con datos, los patrones de composición en el motor de reportes con dataset se combinan limpiamente con los flujos de columna: mida primero, coloque el mobiliario fijo, y luego dele al flujo la región que quede
PDFlibPas es una biblioteca de PDF para Delphi, C++Builder y Lazarus, y el ciclo de vida completo de TextFlow, creación, dibujo, medición, inspección, rebobinado y liberación, también se expone a través de las interfaces DLL y ActiveX. La documentación completa está en la página de la biblioteca PDFlibPas Delphi