Pular para o conteúdo

Fonte: tipos de valor, incorporação e fallback

No NextPDF, uma fonte é representada pelo objeto de valor imutável FontInfo e pelo tipo de tecnologia que informa ao mecanismo como incorporá-la. O mecanismo incorpora todas as fontes que usa. Uma referência legada Base 14 recorre a um substituto empacotado e compatível em métricas.

Terminal window
composer require nextpdf/core:^3

FontInfo é o objeto de valor imutável que fornece ao mecanismo tudo de que ele precisa para incorporar uma fonte: família e estilo, o nome PostScript, flags do descritor, métricas dimensionadas para um em de 1000 unidades, larguras de caractere, o mapa de glifo para Unicode, o mapa de caracteres direto (cmap, de Unicode para identificador de glifo), os bytes brutos da fonte e, quando presentes, eixos de variação, instâncias nomeadas, seletores de variação, pares de kerning e métricas verticais. Ele é final readonly. A assinatura do construtor e as propriedades públicas estão congeladas, de modo que uma fonte analisada é um fato estável e compartilhável. FontInfo::encodeText() é o único método com comportamento. Ele passa pelo resolvedor de codificação e retorna um EncodedGlyphRun.

FontType enumera as tecnologias que o mecanismo incorpora: TrueType (codificação de byte único), TrueTypeUnicode (codificação multibyte por identificador de caractere (CID) para scripts ricos em Unicode), OpenType (contornos Compact Font Format), Type1 (PostScript Type 1, registrada a partir de um par Printer Font Binary (PFB) e Adobe Font Metrics (AFM)) e CidFont0 (uma fonte CID baseada em PostScript). O tipo atribuído pelo analisador determina o formato do dicionário de fonte emitido pelo escritor.

Para manter a renderização independente das fontes instaladas no sistema, o mecanismo incorpora o programa da fonte — ISO 32000-2 §9. Um programa TrueType é incorporado por meio da entrada de descritor de fonte FontFile2 e deve incluir as tabelas glyf, head, hhea, hmtx, loca e maxp — ISO 32000-2 §9.6.5 (resumo RAG truncado pelo limite de licença; registrado em _downgraded-claims-o3.md). Um programa OpenType com uma tabela de contornos Compact Font Format é incorporado por meio de FontFile3 — ISO 32000-2 §9.6.5 (resumo RAG truncado; consulte o mesmo log). O subsetter reconstrói exatamente esse conjunto de tabelas obrigatórias, de modo que o subconjunto incorporado continue sendo um programa em conformidade.

O fallback cobre o caso legado Base 14. Base14SubstituteFonts mapeia uma chave Base 14 normalizada — helvetica, helveticab, times, courier e as demais — para um arquivo Liberation Fonts empacotado. Liberation Sans, Serif e Mono são compatíveis em métricas com Helvetica ou Arial, Times Roman e Courier. Cada uma é uma face TrueType incorporada, de modo que renderiza todo o repertório latino de WinAnsiEncoding (Windows-1252) que uma referência das standard-14 exige — latino acentuado, o sinal de Euro e pontuação tipográfica comum (ISO 32000-2 Annex D.2). Symbol e ZapfDingbats não têm substituto compatível em métricas com licença permissiva; por isso, o NextPDF deliberadamente não os substitui. Um documento que precise de uma dessas fontes deve registrar uma fonte incorporável. O resolvedor não tem efeitos colaterais: ele informa para qual arquivo uma chave é mapeada e nada mais. O chamador continua responsável pelo registro no registry, preservando a semântica de bloqueio e o pipeline de warmup.

TipoEspécieMembros principaisEstabilidadeDesde
FontInfoclasse final readonly$family, $style, $type, $unitsPerEm, $widths, $unicodeMap, $cmapForward, $fileData, $variationAxes, $kernPairs, getKey(), encodeText()estável1.0.0
FontTypeenum (string)TrueType, TrueTypeUnicode, OpenType, Type1, CidFont0estável1.0.0
Base14SubstituteFontsclasse final (interna)chave Base 14 normalizada para o caminho do arquivo Liberation empacotadoestável2.7.0
ShaperFactoryclasse finaldefault(), create(), wouldUseRealShaper()estável3.2.0
ShapingResultclasse final readonly$glyphRuns, $originalText, $script, $direction, $shaperImplestável3.2.0

Base14SubstituteFonts é @internal: de uso exclusivo do framework, sem garantia de compatibilidade retroativa para a sua superfície.

examples/35-cjk-cmap-demo.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Typography\FontRegistry;
use NextPDF\Typography\FontType;
$registry = new FontRegistry();
$font = $registry->register('/path/to/NotoSansTC-Regular.ttf', alias: 'NotoSansTC');
// FontInfo is the immutable parsed fact about the face.
echo $font->family, ' / ', $font->type->value, "\n"; // e.g. "Noto Sans TC / TrueTypeUnicode"
assert($font->type === FontType::TrueTypeUnicode);

O analisador preenche FontInfo e atribui o FontType. Uma face TrueType com mapa de caracteres Unicode torna-se TrueTypeUnicode, que o escritor emite como uma fonte composta Type 0.

examples/font/base14-fallback.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Typography\Base14SubstituteFonts;
use NextPDF\Typography\FontRegistry;
final readonly class Base14EmbeddingResolver
{
public function __construct(private FontRegistry $registry) {}
/**
* Register an embeddable substitute for a legacy Base 14 key so the
* output document embeds every font (PDF/A-4 and PDF/UA-2 require it).
*/
public function ensureEmbeddable(string $base14Key): void
{
$path = Base14SubstituteFonts::resolve($base14Key);
if ($path === null) {
// Symbol / ZapfDingbats have no permissive substitute — the
// caller must supply its own embeddable font.
throw new \RuntimeException("No bundled substitute for {$base14Key}");
}
if (!$this->registry->has($base14Key)) {
$this->registry->register($path, alias: $base14Key);
}
}
}

O resolvedor não tem efeitos colaterais. O registro permanece explícito, de modo que os contratos de bloqueio e de warmup do registry continuam válidos. Symbol e ZapfDingbats não retornam nenhum caminho, por design.

  • Symbol e ZapfDingbats não são substituídos intencionalmente. Um resultado nulo para essas chaves é o comportamento documentado, não um bug de fonte ausente.
  • FontInfo é final readonly. Trate uma fonte analisada como um valor: nunca espere modificar larguras ou métricas no próprio objeto; registre novamente se a origem mudar.
  • Uma fonte Type 1 precisa tanto dos contornos PFB quanto das métricas AFM. FontRegistry::registerType1() recebe o par; a descoberta automática deriva o caminho do AFM a partir do caminho do PFB pela extensão.
  • FontType::TrueType e FontType::TrueTypeUnicode marcam a distinção entre byte único e multibyte. O resolvedor de codificação usa o mapa de caracteres direto preenchido, não o nome da família, de modo que uma face TrueType Unicode seja roteada automaticamente para o caminho Identity-H.
  • Os eixos de variação da fonte e as instâncias nomeadas são analisados para FontInfo quando presentes, mas o exemplo trabalhado de chinês, japonês e coreano (CJK) usa deliberadamente a face estática para manter determinístico o FontInfo analisado.

O registry aloca FontInfo uma vez por fonte por processo e, em seguida, o compartilha por referência. Os bytes brutos da fonte dominam o custo de memória. Aqueça apenas as fontes de que um worker precisa e acompanhe memoryUsage(). O resolvedor de substitutos Base 14 realiza uma busca em mapa de tempo constante, sem input/output (I/O), até que o chamador registre o arquivo resolvido. O performance_budget de 1500 ms de tempo total e 64 MB de pico cobre o aquecimento de um conjunto típico de fontes mais a renderização. Até que o subsetter seja executado, o consumo de memória de cada fonte escala com o tamanho do arquivo da fonte, não com a quantidade de glifos.

FontInfo em si é inerte: dados analisados sem comportamento além da transformação pura encodeText(). A superfície de ataque fica a montante, no momento da análise, quando bytes de fonte arbitrários chegam ao analisador TrueType ou Type 1. Os analisadores verificam os limites de cada deslocamento binário e rejeitam stream wrappers e bytes nulos em caminhos. Antes do registro, a entrada de fonte não confiável deve passar por uma política de recursos externos que limite o tamanho e a quantidade de glifos. Os substitutos Liberation empacotados são recursos confiáveis distribuídos com o pacote, de modo que o caminho de fallback não introduz nenhuma nova entrada não confiável.

AfirmaçãoNormaCláusulaEvidência
Todas as fontes usadas pelo documento são incorporadas para que o documento seja renderizado sem depender de fontes do sistema.ISO 32000-2§9
Um programa TrueType é incorporado por meio de FontFile2 com as tabelas glyf, head, hhea, hmtx, loca, maxp.ISO 32000-2§9.6.5Resumo RAG truncado pelo limite de licença; prefixo 7b26f37996239b2a, consulte _downgraded-claims-o3.md
Um programa OpenType (CFF) é incorporado por meio de FontFile3.ISO 32000-2§9.6.5Resumo RAG truncado pelo limite de licença; prefixo 801549ee00623baf, consulte _downgraded-claims-o3.md

A primeira cláusula é fixada por resumo e corroborada por B1. As cláusulas FontFile2 e FontFile3 são paráfrases. Os resumos RAG completos dessas cláusulas não foram retornados (truncamento pelo limite de licença), de modo que a evidência também é corroborada por FontSubsetter (que reconstrói exatamente o conjunto glyf/head/hhea/hmtx/loca/maxp) e pelo enum FontType. O NextPDF não reproduz texto normativo. No código-fonte, Base14SubstituteFonts cita ISO 32000-2 §9.6.2.2 (tratamento de fontes Type 1 padrão), ISO 14289-2:2024 §8.4.5.5.1 (incorporação de fontes do PDF/UA-2) e ISO 19005-4:2020 §6.3.5 (incorporação de fontes do PDF/A-4). As páginas de acessibilidade e conformidade apresentam a conformidade completa dos perfis.

Um pacote comercial de licenciamento de fontes e um serviço de subsetting dinâmico se baseiam no FontInfo do Core e no registry. O módulo de fontes do Core incorpora, faz subsetting e recorre ao fallback sem licença. A omissão do link de conversão é intencional.