Texto justificado — margens alinhadas tanto à esquerda como à direita — é a norma tipográfica para documentos profissionais, contratos e publicações. O que parece simples de descrever é mais subtil de implementar corretamente. O espaçamento tem de ser distribuído de forma precisa entre palavras, a última linha de um parágrafo não deve ser esticada para corresponder às margens, e o comportamento correto tem de diferir entre scripts latinos onde o espaço entre palavras é o vetor de ajuste e scripts CJK onde o espaço entre caracteres é apropriado em vez disso. O HotPDF trata de tudo isto através de WideTextOutBox com o tipo de justificação jtJustify
As quatro opções de justificação
A enumeração THPDFJustificationType tem quatro membros: jtLeft, jtCenter, jtRight e jtJustify. Os primeiros três comportam-se como seria de esperar. jtJustify produz texto com ambas as margens alinhadas ao retângulo da caixa de texto passado para WideTextOutBox. A última linha de cada parágrafo é tratada como alinhada à esquerda, o que é o comportamento tipográfico correto: esticar uma linha final com apenas duas palavras produziria lacunas de aspeto estranho
PDF.WideTextOutBox(
X, Y, // top-left corner of the text box in points
Width, Height, // box dimensions
LineSpacing, // extra leading between lines
Text, // the paragraph to flow
Font, // active font object
FontSize,
jtJustify // full justification
);
O método flui o texto para caber dentro da caixa, calcula qual o espaçamento de palavras que cada linha necessita para atingir a margem direita e emite os operadores de texto PDF correspondentes. O código chamador passa a caixa e o texto; a biblioteca trata da aritmética de justificação linha a linha
A medição que alimenta o cálculo
Justificar uma linha requer conhecer quanto espaço os seus glifos ocupam antes de qualquer ajuste de espaçamento. Isso exige medições de largura de caracteres individuais — não apenas a largura total da cadeia de caracteres, mas as larguras de cada glifo para que os avanços possam ser redistribuídos com precisão
A função GetWideCharAdvances fornece essas medições. Dada uma cadeia de caracteres e um objeto de fonte, devolve um array de larguras de avanço em unidades de ponto, uma por ponto de código. O loop de justificação lê o array para calcular a largura atual da linha, determina o espaço restante e divide-o uniformemente entre os intervalos de palavras na linha
O que torna isso eficiente não é apenas a API, mas como a medição subjacente é obtida. O HotPDF usa GetWideCharAdvances da API Win32 GDI para recuperar avanços para um bloco de caracteres numa única chamada. Isso é cerca de 80 vezes mais rápido do que calcular a largura de cada caractere individualmente com chamadas GDI separadas — uma diferença que se torna visível ao justificar parágrafos longos em páginas densas, como relatórios de contrato ou documentos de política
Scripts latinos versus CJK
A justificação latina distribui espaço nos limites de palavras. Uma linha com seis palavras e quatro lacunas distribui o espaço excedente entre as quatro lacunas entre palavras. Isso é o que os leitores ocidentais esperam e é o que produz texto justificado de aparência natural em português
O texto CJK funciona de forma diferente. Os scripts chinês, japonês e coreano não usam espaços como separadores de palavras, portanto o espaço entre palavras não tem nenhum lugar onde possa ser expandido de forma significativa. Para esses scripts, a justificação distribui espaço entre cada par de caracteres adjacentes. O HotPDF deteta o script examinando os intervalos de pontos de código e seleciona o algoritmo de distribuição de acordo — espaçamento entre palavras para texto Latino, entre caracteres para CJK — por isso o mesmo código de chamada funciona corretamente para texto em qualquer idioma
A última linha
Um detalhe que separa a justificação implementada corretamente da justificação ingénua: a última linha de um parágrafo. Se um parágrafo terminar com uma linha com apenas algumas palavras e muito espaço em branco, esticar essa linha para atingir a margem direita cria lacunas tão largas que parecem erros. O comportamento tipográfico correto é deixar a última linha alinhada à esquerda, que é o que WideTextOutBox faz. A linha final recebe o espaçamento padrão de palavras do tipo de letra em vez do espaçamento expandido aplicado às linhas completas
Misturar justificação com outros estilos de alinhamento
Nem cada bloco de texto num documento deve ser justificado. Títulos geralmente ficam melhor centrados ou alinhados à esquerda. As legendas podem ser centralizadas. Um documento típico usa jtLeft ou jtCenter para títulos e jtJustify para o corpo do texto. Uma vez que o tipo de justificação é passado por chamada para WideTextOutBox, é simples misturar estilos num único documento sem alterar qualquer estado global
// Heading: centred
PDF.WideTextOutBox(X, Y, Width, HeadingHeight, 0, HeadingText, Font, 16, jtCenter);
// Body paragraph: justified
PDF.WideTextOutBox(X, Y2, Width, BodyHeight, LineSpacing, BodyText, Font, 11, jtJustify);
// Caption: left-aligned
PDF.WideTextOutBox(X, Y3, Width, CaptionHeight, 0, CaptionText, Font, 9, jtLeft);
O tipo de fonte passado para cada chamada pode igualmente diferir, pelo que cabeçalhos a negrito, corpo de texto regular e legendas em itálico são independentemente controláveis
Texto RTL
Para texto árabe e hebraico onde a direção de leitura vai da direita para a esquerda, o HotPDF fornece RTLTextOutBox para fluxo de texto de direita para esquerda. O tipo de justificação jtJustify aplica-se igualmente lá, com distribuição de espaço nas posições de lacunas de palavras corretas para o script. O artigo sobre RTLTextOut abrange esse caminho em detalhe
A justificação faz parte de um conjunto de ferramentas de composição de texto mais amplo. O fluxo de texto multilinha, o controlo de espaçamento de linhas e o posicionamento de texto em caixas delimitadas são descritos em o guia de saída de texto do HotPDF. A disposição de texto vertical para scripts orientados em coluna está em disposição de texto vertical. Todas as funcionalidades de composição de texto estão disponíveis no Componente HotPDF para Delphi e C++Builder