Salta ai contenuti

Font: oggetti valore, incorporamento e fallback

In NextPDF un font è rappresentato dall’oggetto valore immutabile FontInfo e dal tipo di tecnologia che determina come il motore lo incorpora. Ogni font utilizzato dal motore viene incorporato. Un riferimento legacy Base 14 usa un sostituto metricamente compatibile incluso nel pacchetto.

Terminal window
composer require nextpdf/core:^3

FontInfo è l’oggetto valore immutabile che contiene tutto ciò che serve al motore per incorporare un font: famiglia e stile, nome PostScript, flag del descrittore, metriche scalate su un em di 1000 unità, larghezze dei caratteri, mappa glifo-Unicode, cmap diretta (da Unicode a identificatore di glifo), byte grezzi del font e, se presenti, assi di variazione, istanze denominate, selettori di variazione, coppie di crenatura e metriche verticali. È final readonly. La firma del costruttore e le proprietà pubbliche sono bloccate, quindi un font analizzato è un dato stabile e condivisibile. FontInfo::encodeText() è l’unico metodo che esegue lavoro effettivo: passa attraverso il resolver di codifica e restituisce un EncodedGlyphRun.

FontType enumera le tecnologie che il motore incorpora: TrueType (codifica a byte singolo), TrueTypeUnicode (codifica CID multibyte per script con ampia copertura Unicode), OpenType (contorni Compact Font Format), Type1 (PostScript Type 1, registrato tramite una coppia PFB e AFM) e CidFont0 (un font CID basato su PostScript). Il tipo assegnato dal parser determina la forma del dizionario font emesso dal writer.

Il motore incorpora il programma del font in modo che il documento venga visualizzato nello stesso modo in qualsiasi visualizzatore, indipendentemente dai font di sistema installati — ISO 32000-2 §9. Un programma TrueType viene incorporato tramite la voce del descrittore font FontFile2 e deve includere le tabelle glyf, head, hhea, hmtx, loca e maxp — ISO 32000-2 §9.6.5 (digest RAG troncato dal limite di licenza; registrato in _downgraded-claims-o3.md). Un programma OpenType con una tabella di contorni Compact Font Format viene incorporato tramite FontFile3 — ISO 32000-2 §9.6.5 (digest RAG troncato; vedere lo stesso log). Il subsetter ricostruisce esattamente questo set di tabelle richieste, quindi il subset incorporato resta un programma conforme.

Il fallback gestisce il caso legacy Base 14. Base14SubstituteFonts associa una chiave Base 14 normalizzata — helvetica, helveticab, times, courier e le altre — a un file Liberation Fonts incluso nel pacchetto. Liberation Sans, Serif e Mono sono metricamente compatibili con Helvetica o Arial, Times Roman e Courier. Ciascuno è una face TrueType incorporata e quindi rende l’intero repertorio latino WinAnsiEncoding (Windows-1252) richiesto da un riferimento standard-14 — latino accentato, il segno dell’euro e la punteggiatura tipografica comune (ISO 32000-2 Annex D.2). Symbol e ZapfDingbats non hanno alcun sostituto metricamente compatibile con licenza permissiva e non vengono sostituiti per scelta esplicita; un documento che ne ha bisogno deve registrare un font incorporabile. Il resolver è privo di effetti collaterali: indica solo a quale file è associata una chiave, nulla di più. La registrazione nel registry resta responsabilità del chiamante; questo preserva la semantica del lock e la pipeline di warmup.

TipoGenereMembri principaliStabilitàA partire da
FontInfoclasse final readonly$family, $style, $type, $unitsPerEm, $widths, $unicodeMap, $cmapForward, $fileData, $variationAxes, $kernPairs, getKey(), encodeText()stabile1.0.0
FontTypeenum (string)TrueType, TrueTypeUnicode, OpenType, Type1, CidFont0stabile1.0.0
Base14SubstituteFontsclasse final (interna)mappa da chiave Base 14 normalizzata a percorso del file Liberation incluso nel pacchettostabile2.7.0
ShaperFactoryclasse finaldefault(), create(), wouldUseRealShaper()stabile3.2.0
ShapingResultclasse final readonly$glyphRuns, $originalText, $script, $direction, $shaperImplstabile3.2.0

Base14SubstituteFonts è @internal: solo per uso interno al framework; la sua superficie non offre garanzie di retrocompatibilità.

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);

Il parser popola FontInfo e assegna il FontType. Una face TrueType con cmap Unicode viene classificata come TrueTypeUnicode, che il writer emette come font composito 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);
}
}
}

Il resolver è privo di effetti collaterali. La registrazione resta esplicita affinché i contratti di lock e di warmup del registry rimangano validi. Symbol e ZapfDingbats non restituiscono alcun percorso per scelta progettuale.

  • Symbol e ZapfDingbats non vengono sostituiti per scelta esplicita. Un risultato null per quelle chiavi è il comportamento documentato, non un errore dovuto a un font mancante.
  • FontInfo è final readonly. Trattare un font analizzato come un valore: non aspettarsi mai di poter modificare larghezze o metriche sul posto; registrarlo di nuovo se la sorgente cambia.
  • Un font Type 1 richiede sia il contorno PFB sia le metriche AFM. FontRegistry::registerType1() accetta la coppia; il rilevamento automatico deriva il percorso AFM dal percorso PFB tramite l’estensione.
  • FontType::TrueType rispetto a FontType::TrueTypeUnicode è la distinzione tra codifica a byte singolo e codifica multibyte. Il resolver di codifica si basa sulla cmap diretta popolata, non sul nome della famiglia, quindi una face TrueType Unicode viene instradata automaticamente sul percorso Identity-H.
  • Gli assi dei font variabili e le istanze denominate, quando presenti, vengono analizzati in FontInfo, ma l’esempio CJK completo usa intenzionalmente la face statica per mantenere deterministico il FontInfo analizzato.

Il registry alloca FontInfo una sola volta per font e per processo, poi lo condivide per riferimento. Trasporta i byte grezzi del font, che costituiscono il costo di memoria predominante. Un worker dovrebbe precaricare solo i font di cui ha bisogno e monitorare memoryUsage(). Il resolver sostitutivo Base 14 è una ricerca su mappa a tempo costante, senza I/O finché il chiamante non registra il file risolto. Il performance_budget di 1500 ms di tempo reale e 64 MB di picco copre il warmup di un set di font tipico più il rendering. L’impronta di memoria per font cresce con la dimensione del file del font, non con il numero di glifi, fino all’esecuzione del subsetter.

FontInfo di per sé è inerte: è un insieme di dati analizzati, privo di comportamento oltre la pura trasformazione encodeText(). La superficie di attacco è a monte, in fase di analisi: byte di font arbitrari che raggiungono il parser TrueType o Type 1. I parser controllano i limiti di ogni offset binario e rifiutano gli stream wrapper e i byte null nei percorsi. L’input di font non attendibile deve superare una policy per le risorse esterne che limita dimensione e numero di glifi prima della registrazione. I sostituti Liberation inclusi sono asset attendibili distribuiti con il pacchetto, quindi il percorso di fallback non introduce nuovo input non attendibile.

DichiarazioneStandardClausolaEvidenza
Ogni font utilizzato dal documento viene incorporato, così il documento viene visualizzato senza dipendere dai font di sistema.ISO 32000-2§9
Un programma TrueType viene incorporato tramite FontFile2 con le tabelle glyf, head, hhea, hmtx, loca, maxp.ISO 32000-2§9.6.5Digest RAG troncato dal limite di licenza; prefisso 7b26f37996239b2a, vedere _downgraded-claims-o3.md
Un programma OpenType (CFF) viene incorporato tramite FontFile3.ISO 32000-2§9.6.5Digest RAG troncato dal limite di licenza; prefisso 801549ee00623baf, vedere _downgraded-claims-o3.md

La prima clausola è ancorata tramite digest e corroborata da B1. Le clausole FontFile2 e FontFile3 sono parafrasate. I loro digest RAG completi non sono stati restituiti (troncamento per il limite di licenza) e sono corroborati da FontSubsetter (che ricostruisce esattamente il set glyf/head/hhea/hmtx/loca/maxp) e dall’enum FontType. NextPDF non riproduce testo normativo. Base14SubstituteFonts cita nel codice sorgente ISO 32000-2 §9.6.2.2 (gestione standard dei font Type 1), ISO 14289-2:2024 §8.4.5.5.1 (incorporamento dei font PDF/UA-2) e ISO 19005-4:2020 §6.3.5 (incorporamento dei font PDF/A-4). Le pagine sull’accessibilità e sulla conformità documentano la piena conformità ai profili.

Un pacchetto commerciale per le licenze dei font e un servizio di subsetting dinamico si basano su FontInfo e sul registry di Core. Il modulo font di Core incorpora, esegue il subsetting e ricorre al fallback senza richiedere alcuna licenza. L’omissione di un link di conversione è intenzionale.