O PDFlibPas desenha texto japonês e chinês ao longo da página, de cima para baixo. SetVerticalWritingMode liga a escrita vertical, as chamadas comuns de DrawText passam a correr para baixo, e GetVerticalWritingMode reporta o estado atual. Antes de isto existir, compor texto verticalmente significava colocar cada carácter à mão e esperar que o espaçamento parecesse correto
A escrita vertical não é texto horizontal rodado noventa graus. Os caracteres mantêm-se direitos, o avanço corre de cima para baixo em vez de atravessar, e vários caracteres mudam inteiramente de forma — que é a parte que separa um documento que se lê naturalmente de um que um leitor japonês reconhece imediatamente como produzido por máquina
O que muda dentro do PDF
O texto desenhado desta forma passa por um tipo de letra Type0 em modo de escrita vertical que transporta as métricas verticais próprias do tipo. Isso importa em duas direções. Um leitor avança cada carácter pela distância que o seu designer pretendia em vez de por um passo uniforme, pelo que a coluna tem o ritmo para que o tipo foi desenhado. E copiar o texto devolve os caracteres originais, porque a execução vertical continua a ser texto real com um mapeamento próprio em vez de uma sequência de glifos posicionados
Um tipo que não transporta métricas verticais próprias avança um em por carácter, que é o que um leitor faria com a predefinição. Esse recurso de recurso vale a pena conhecer porque é a diferença que se vê quando um documento renderiza corretamente com um tipo CJK apropriado e parece mecanicamente espaçado com um tipo latino que por acaso contém algum kana
var
Lib: TPDFlib;
H: Double;
begin
Lib := TPDFlib.Create;
try
Lib.SetOrigin(1);
Lib.AddTrueTypeFont('MS Mincho', 1); // 1 = embed the face
Lib.SetTextSize(12);
Lib.SetVerticalWritingMode(1); // ordinary DrawText now runs down
H := Lib.GetVerticalTextHeight('MS Mincho', 12, '第三章 保守点検');
Lib.DrawText(480, 72, '第三章 保守点検');
Lib.SetVerticalWritingMode(0); // back to horizontal
Lib.DrawText(72, 72 + H, 'Chapter 3');
Lib.SaveToFile('manual-ja.pdf');
finally
Lib.Free;
end;
end;
Porque razão é que os parênteses se parecem errados em texto vertical?
Porque um parêntese tem duas formas e só uma delas pertence a uma coluna. Os parênteses, a marca de vogal longa e os kana pequenos são desenhados de forma diferente quando o texto corre de cima para baixo — um parêntese roda para se sentar ao longo da coluna em vez de se deitar atravessado, e a marca de vogal longa torna-se um traço vertical. Desenhe as formas horizontais numa coluna vertical e cada um deles fica deitado ao lado
O PDFlibPas tira as formas da funcionalidade vertical do próprio tipo de letra, pelo que cada tipo fornece o que o seu designer desenhou em vez de uma substituição adivinhada a partir do carácter. Essa distinção importa para a correção: uma tabela de substituição adivinhada está certa para os casos comuns e errada para os tipos que tratam um carácter de forma diferente, e um tipo que não nomeia formas verticais é desenhado exatamente como antes em vez de ser forçado através de uma tabela para a qual nunca pediu
GetVerticalTextHeight mede as formas que vão efetivamente ser desenhadas, pelo que uma coluna cujos caracteres mudam de forma continua a ser medida corretamente. Medir as formas horizontais e desenhar as verticais é a fonte clássica de colunas que excedem a sua caixa em alguns caracteres
Desenhar uma execução sem mudar o modo
DrawVerticalText desenha uma única execução na vertical, recebendo a posição, o nome do tipo, o tamanho e o texto, e deixa o modo de escrita em paz. Use-a para a exceção vertical dentro de um documento horizontal — uma etiqueta de lombo, um carimbo, uma única coluna de nomes — em que ligar e desligar um modo global em cada chamada é mais estado do que a tarefa merece
As formas horizontal e vertical de um único tipo são mantidas separadas internamente, pelo que uma página pode transportar ambas sem que uma perturbe a outra. É o que torna prática uma página mista: uma página de livro japonês com corpo vertical e cabeçalhos correntes horizontais, ou um certificado chinês com um título vertical sobre linhas de detalhe horizontais
// One vertical run inside an otherwise horizontal page
Lib.DrawVerticalText(520, 96, 'MS Mincho', 14, '保守点検記録');
// The horizontal text around it is unaffected
Lib.DrawText(72, 96, 'Maintenance inspection record');
Acertar o tipo de letra antes de tudo o resto
A escrita vertical depende inteiramente do tipo. Um tipo CJK com métricas verticais próprias e uma funcionalidade vertical produz saída correta sem mais trabalho; um tipo sem elas produz caracteres direitos que avançam um em de cada vez e sem qualquer mudança de forma. Se o texto vertical parecer subtly errado, examine o tipo antes de examinar o código
O embutir segue as regras habituais e os custos habituais. Um tipo CJK completo é grande, pelo que o subsetting não é opcional para documentos que vão para qualquer lado — as notas sobre otimização do tamanho do ficheiro PDF e subsetting de tipos de letra cobrem o que esperar, e o guia de embutir tipos de letra em falta num PDF existente cobre o caso de reparação em que um documento vertical chega sem os seus tipos
Onde o texto vertical ainda precisa de uma decisão de composição sua
Da ordem das colunas. O texto vertical japonês corre da direita para a esquerda por coluna, pelo que uma página de duas colunas começa no limite direito, e nenhuma definição de modo de escrita consegue inferir isso a partir do texto. O mesmo se aplica à ordem das páginas num documento que se lê da direita para a esquerda como um todo, e a onde o furigana, as notas de rodapé e as legendas das figuras se sentam
O que a biblioteca garante é que cada execução é composta corretamente: formas corretas, avanços corretos, texto extraível. Para onde vão as execuções na página é um problema de composição, e para documentos montados a partir de dados o guia de pesquisa de texto e enumeração de elementos de página é útil para verificar depois que o que foi para a página é o que pretendia
O PDFlibPas é uma biblioteca PDF nativa em Pascal para Delphi, C++Builder e Lazarus, e a escrita CJK vertical faz parte da API de desenho em vez de ser um extra — veja a página do produto PDFlibPas para a lista de funcionalidades de texto e tipos de letra