Fontes: a parte difícil
ISO 32000-2 §9 Evidence: Mixed evidence
Visão geral
Seção intitulada “Visão geral”As fontes são o ponto em que um PDF pode parecer perfeitamente correto e, ainda assim, estar silenciosamente quebrado. Uma página pode renderizar os glifos certos e mesmo assim ser impossível de pesquisar, impossível de copiar como texto e não estar conforme a um perfil de arquivamento. Tudo isso pode acontecer ao mesmo tempo, sem nenhum sinal visível para avisar você. Esta página trata das três coisas que precisam funcionar corretamente — incorporação, subsetting, codificação — e do que o NextPDF faz em cada uma delas.
Por que isso importa
Seção intitulada “Por que isso importa”“Está com boa aparência” é a frase mais perigosa no trabalho com PDF, e as fontes são onde ela causa mais estrago. Três condições independentes precisam ser atendidas:
- Incorporação — o programa de fonte segue junto no arquivo, de modo que ele renderize da mesma forma em uma máquina que não tem a fonte instalada.
- Subsetting — só os glifos realmente usados são incluídos, de modo que uma fonte CJK de 20 MB não infle todos os documentos.
- Codificação — existe um mapa correto dos códigos de caractere na página de volta para o Unicode, de modo que o texto possa ser pesquisado, copiado, indexado e lido por tecnologia assistiva.
A renderização visual só comprova parte da primeira condição. Um documento pode exibir glifos perfeitos e ainda assim falhar completamente na terceira — o texto é uma imagem de palavras, não palavras de fato. Essa é a falha que passa por toda revisão do tipo “está com boa aparência” e depois compromete uma auditoria de conformidade ou uma solicitação de descoberta judicial (discovery).
A versão resumida
Seção intitulada “A versão resumida”- Uma fonte em um PDF é um dicionário mais, geralmente, um stream de programa de fonte incorporado.
- Subsetting reescreve esse programa para conter apenas os glifos usados. O nome de uma fonte com subconjunto recebe uma tag de seis letras maiúsculas e um
+para que os leitores a tratem como distinta. - Codificação é o problema separado de mapear códigos de caractere para Unicode. Uma CMap
/ToUnicodeé o que torna o texto pesquisável e copiável — e ela é independente de os glifos parecerem corretos ou não. - Texto com boa aparência sem (ou com uma incorreta)
/ToUnicodeé a clássica falha silenciosa: perfeito na tela, impossível de pesquisar na prática. - O NextPDF cria subconjuntos de fontes TrueType, preserva a identidade dos glifos para a renderização correta e emite uma CMap
/ToUnicodepara que a extração funcione — e pode impor a regra de incorporação do PDF 2.0 em vez de apenas avisar.
Como o NextPDF aborda isso
Seção intitulada “Como o NextPDF aborda isso”Subsetting. O FontSubsetter (src/Typography/FontSubsetter.php) analisa o diretório de tabelas TrueType original e lê a cmap para mapear pontos de código Unicode para IDs de glifo. Ele lida tanto com o formato 4 do BMP quanto com o formato 12 de Unicode completo, necessário para CJK. Em seguida, executa o passo que subsetters ingênuos costumam deixar passar: resolve as dependências de glifos compostos por fecho transitivo. Um glifo acentuado construído a partir de uma letra-base mais uma marca de combinação referencia outros glifos como componentes. Se esses componentes forem descartados, o glifo é renderizado incorretamente. O subsetter percorre esse grafo até não surgir nenhum componente novo, com proteção contra ciclos para que uma fonte malformada não entre em laço infinito.
Vale destacar duas escolhas de engenharia nesse arquivo. Primeiro, os IDs de glifo são preservados, não remapeados — os slots não usados são preenchidos com zeros em glyf/loca para que os índices de glifo originais do fluxo de conteúdo continuem válidos sob CIDToGIDMap /Identity. Remapear geraria um arquivo menor, mas exigiria reescrever toda referência de glifo. Preservar a identidade é correto por construção. Segundo, o percurso é ordenado (gid em ordem crescente) para que o subconjunto seja determinístico em nível de bytes — a mesma fonte e os mesmos glifos usados produzem os mesmos bytes de subconjunto, exatamente o que builds reproduzíveis exigem. Se o subsetting economizaria menos de ~10% do arquivo, a fonte original é retornada sem alterações. O custo não compensa um ganho marginal.
Incorporação. Uma política explícita decide se um programa de fonte é incluído ou não — nunca por adivinhação. O Pdf20FontEmbeddingPolicy (src/Writer/Pdf20FontEmbeddingPolicy.php) tem dois modos. Sob o perfil PDF 2.0, o Strict rejeita uma referência a um Type 1 padrão não incorporado (“Base14”) com uma exceção tipada — o comportamento correto em termos de conformidade. O AllowBase14 preserva o caminho histórico de aviso. Durante uma janela de migração, ele emite o descritor de fonte mínimo que o padrão ainda exige e despacha um aviso em vez de lançar uma exceção. O chamador faz a escolha explicitamente no documento; ela nunca é inferida a partir da fonte.
Codificação. Para fontes compostas (Type 0), o EmbeddedTtfFontDictBuilder (src/Writer/EmbeddedTtfFontDictBuilder.php) emite o descendente CIDFontType2, o pai Type0 e um stream de CMap /ToUnicode para que os códigos de caractere sejam resolvidos de volta para Unicode. O stream /ToUnicode só está legitimamente ausente em um caso: quando uma CMap CJK predefinida e autodescritiva já fornece ao leitor o mapeamento de caractere para Unicode. Nesse caso, a CMap é a codificação, então o perfil simples omite um stream /ToUnicode redundante para economizar bytes. Fora desse caso, o stream /ToUnicode é o que mantém o texto como texto.
| Aspecto | O que garante | O que não garante | Falha silenciosa se estiver errado |
|---|---|---|---|
| Incorporação | Mesma renderização sem a fonte instalada | Que o texto é pesquisável | Fonte substituída; métricas erradas em outra máquina |
| Subsetting | Arquivo pequeno; apenas os glifos usados | Qualquer coisa sobre codificação | Componentes compostos ausentes → glifos acentuados quebrados |
Codificação (/ToUnicode) | Texto pesquisável, copiável e acessível | Que os glifos sejam renderizados corretamente | Página de aparência perfeita, impossível de pesquisar / ilegível ao copiar |
As três preocupações com fontes são independentes. Incorporação e subsetting tratam de aparência e tamanho; codificação trata de significado. Uma página pode passar nas duas primeiras e falhar na terceira sem nada visível para mostrar isso.
O que as evidências dizem
Seção intitulada “O que as evidências dizem”A regra de nomenclatura de subconjuntos é normativa e precisa.
Spec: ISO 32000-2, §9.9.2 ISO 32000-2 §9.9.2 exige que o nome PostScript de um
subconjunto de fonte — o BaseFont e o FontName do descritor —
comece com uma tag de exatamente seis letras maiúsculas, depois um sinal de mais,
e então o nome PostScript da fonte original. Ela também exige que diferentes
subconjuntos da mesma fonte em um único arquivo usem tags diferentes. Essa regra é o que
permite que um leitor diferencie dois subconjuntos e mescle documentos corretamente. Evidence: Standard-backed
A codificação é uma cláusula separada da renderização.
Spec: ISO 32000-2, §9.10.3 ISO 32000-2 §9.10.3 define a /ToUnicode
como um stream que contém uma CMap que mapeia códigos de caractere para valores Unicode,
e o procedimento de extração de texto em
Spec: ISO 32000-2, §9.10.2 ISO 32000-2 §9.10.2 usa essa CMap para
converter códigos de caractere em Unicode para pesquisa e indexação. Nada no
mecanismo de pintura de glifos toca em /ToUnicode — é exatamente por isso que
o texto pode parecer correto e extrair errado.
Quanto à incorporação, o padrão afirma que a maioria dos dicionários de fonte carrega um descritor de fonte cujo stream de arquivo de fonte incorporado é opcional, mas fortemente recomendado. O PDF 2.0 torna isso mais rígido especificamente para as catorze fontes Type 1 padrão. A política NextPDF Strict é a leitura correta desse endurecimento em termos de conformidade. O AllowBase14 é a saída de compatibilidade retroativa explícita e opcional — o motor nunca faz um downgrade silencioso.
| Edition | Availability |
|---|---|
| Core | Disponível. Subsetting, emissão de |
| Pro | Adiciona imposição de conformidade e relatórios mais aprofundados sobre incorporação de fontes em nível de perfil. |
| Enterprise | Adiciona a mesma imposição de conformidade sob a superfície operacional enterprise. |
Exemplo prático
Seção intitulada “Exemplo prático”Aqui estão as duas metades de uma fonte composta corretamente incorporada, com subconjunto e pesquisável. A tag de subconjunto segue a regra de seis letras do padrão; a referência /ToUnicode mantém o texto extraível.
% The Type 0 (composite) font dictionary20 0 obj<< /Type /Font /Subtype /Type0 /BaseFont /ABCDEF+NotoSans % six-letter subset tag + '+' /Encoding /Identity-H /DescendantFonts [21 0 R] /ToUnicode 23 0 R >> % the map that makes text searchableendobj
% The descendant CIDFontType2 (carries the subsetted program)21 0 obj<< /Type /Font /Subtype /CIDFontType2 /BaseFont /ABCDEF+NotoSans /CIDToGIDMap /Identity % glyph IDs preserved, not remapped /FontDescriptor 22 0 R >>endobjO /ToUnicode 23 0 R do objeto 20 é a diferença entre um documento pesquisável e a imagem de um documento. Remova-o (fora do caso de CMap predefinida) e cada glifo ainda será pintado perfeitamente, mas uma pesquisa por qualquer palavra na página não encontrará nada.
Equívoco comum
Seção intitulada “Equívoco comum”A armadilha, em termos simples: glifos renderizados corretamente não dizem nada sobre o texto ser texto de fato. A renderização segue o caminho da codificação para o glifo. Pesquisa e cópia seguem o caminho do código para Unicode (/ToUnicode). São mecanismos diferentes, lendo partes diferentes do dicionário de fonte. Portanto, um documento pode ter saída visual impecável e uma /ToUnicode ausente ou incorreta. O resultado é uma página que parece confiável e é funcionalmente impossível de pesquisar — a falha que sobrevive a toda revisão visual porque, por definição, não há nada para ver.
Uma armadilha relacionada: presumir “a fonte está incorporada, então estamos seguros para arquivamento.” A incorporação é necessária, mas não suficiente. Um perfil como PDF/A também espera subconjuntos nomeados conforme a regra de seis letras e codificação correta. Incorporado, mas impossível de pesquisar, ainda falha.
Limites e fronteiras
Seção intitulada “Limites e fronteiras”O subsetter do NextPDF é especificamente um subsetter de TrueType. Ele requer as tabelas TrueType essenciais e retorna a fonte original sem alterações quando elas estão ausentes ou quando o ganho fica abaixo do limiar de ~10%. O subsetting e uma CMap /ToUnicode tornam o texto extraível, mas não conseguem resgatar uma fonte de origem que não tem as informações necessárias para mapear um glifo de volta a um caractere significativo. Quando nenhum valor Unicode pode ser determinado, nenhuma emissão de CMap consegue inventar um.
Esta página trata da produção de uma estrutura de fonte correta em documentos que o NextPDF escreve. Ela não é uma ferramenta de reparo de fontes para PDFs de entrada arbitrários. E emitir um subconjunto e uma codificação conformes não certifica, por si só, um documento em relação a um perfil de arquivamento completo — essa é uma verificação separada e mais ampla.
Mini-FAQ
Seção intitulada “Mini-FAQ”Por que a tag de seis letras — por que não o nome da fonte? Para que um leitor consiga distinguir dois subconjuntos diferentes da mesma fonte e mesclar documentos sem colidir seus conjuntos de glifos. Subconjuntos diferentes, tags diferentes, por regra.
Quando é aceitável não ter /ToUnicode? Quando uma CMap CJK predefinida e autodescritiva já fornece o mapeamento de caractere para Unicode. Nesse caso, a CMap é a codificação. Uma /ToUnicode separada seria redundante. Fora disso, a ausência dela é um defeito.
O subsetting alguma vez prejudica? Apenas se for feito de forma errada. Descartar componentes de glifos compostos quebra os glifos acentuados. Remapear IDs de glifo sem reescrever as referências quebra a renderização. O NextPDF evita os dois problemas resolvendo o fecho de componentes e preservando a identidade dos glifos.
Documentos relacionados
Seção intitulada “Documentos relacionados”- Streams e filtros — os programas de fonte incorporados são objetos de stream filtrados com seu próprio contrato de decodificação.
- O que um PDF realmente é — o modelo de objetos em que vivem os dicionários de fonte e os streams de programa.
- PDF 2.0: o que mudou — incluindo as expectativas mais rígidas de incorporação de fontes da linha de base 2.0.
Glossário
Seção intitulada “Glossário”- Programa de fonte incorporado — o arquivo de fonte propriamente dito (TrueType/CFF/Type 1) carregado dentro do PDF como um stream, de modo que a renderização não dependa das fontes instaladas no leitor.
- Subsetting — reescrever um programa de fonte para conter apenas os glifos que o documento usa, reduzindo o tamanho.
- Tag de subconjunto — o prefixo obrigatório de seis letras maiúsculas mais
+no nome de uma fonte com subconjunto (por exemplo,ABCDEF+NotoSans). /ToUnicode— um stream de CMap que mapeia códigos de caractere para valores Unicode; o que torna o texto do PDF pesquisável, copiável e acessível.- Glifo composto — um glifo construído referenciando outros glifos como componentes; seus componentes devem ser mantidos ao fazer o subsetting.
CIDToGIDMap /Identity— o modo em que os índices de glifo do fluxo de conteúdo são os próprios IDs de glifo da fonte, sem alteração; o NextPDF preserva a identidade dos glifos para que isso continue válido.- Base14 — as catorze fontes Type 1 padrão; o PDF 2.0 espera que as fontes sejam incorporadas em vez de referenciadas pelo nome.