Testo: giunzione di shaping, CJK e gestione delle run
In breve
Sezione intitolata “In breve”Il modulo di testo è la giunzione di shaping: una piccola interfaccia che trasforma una run UTF-8 in glifi posizionati, un backend OpenType reale quando disponibile, un fallback deterministico quando non lo è e un registry per gli shaper specifici per script.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Panoramica concettuale
Sezione intitolata “Panoramica concettuale”ShaperInterface è la giunzione tra la pipeline di layout del testo e un motore di shaping OpenType. È volutamente minimale: un solo metodo shape() che consuma un ShaperInput e restituisce uno ShapingResult. Il tipo di ritorno è l’unico output visibile al consumer: le implementazioni non devono esporre i dettagli interni del motore di shaping e il ritorno tipizzato lo impone a livello strutturale. ShapingResult contiene l’elenco dei record GlyphRun, il testo di origine restituito, lo script, la direzione e un tag shaperImpl che indica quale backend ha prodotto il risultato.
La selezione del backend è esplicita e trasparente sulle capacità disponibili. ShaperFactory esegue una sola volta un probe delle capacità: se l’host dispone di un binding HarfBuzz funzionante, create() restituisce lo shaper basato su HarfBuzz. In caso contrario restituisce NullShaper. NullShaper è un fallback pass-through. Emette un glifo sintetico per ogni codepoint Unicode con avanzamenti pari a zero e offset pari a zero. Contrassegna il risultato in modo che l’osservabilità possa rilevare il fallback. Lascia la risoluzione degli avanzamenti al modulo delle metriche dei font. Si tratta di un percorso degradato documentato, non di uno shaping completo: sostituzione, legature, posizionamento dei segni e forme contestuali richiedono il backend reale. wouldUseRealShaper() è un predicato diagnostico. Il codice di produzione dovrebbe invece diramare in base al tag shaperImpl del risultato.
Lo shaping specifico per script è un SPI, non un’implementazione inclusa nel pacchetto. ScriptShaperRegistry è un registry in stile PSR-11 che risolve un MongolianShaperInterface o un TibetanShaperInterface in base al tag di script ISO 15924. Il registry memorizza le chiavi senza distinzione tra maiuscole e minuscole e delega l’ammissibilità del codice di script a un’unica fonte attendibile. Il registry e le interfacce degli shaper di script costituiscono un contratto congelato, così un’estensione può registrare un provider di Fase 12 senza modificare i punti di chiamata. Il motore fornisce la giunzione; i provider per script complessi sono forniti dal consumer.
La gestione delle run CJK si appoggia alla giunzione di codifica della tipografia. Un face TrueType CJK incorporato viene emesso come font di Tipo 0 con una CMap Identity-H e un discendente CIDFontType2 — ISO 32000-2 §9.7.4 (digest RAG troncato dal limite di licenza; registrato in _downgraded-claims-o3.md). Quando il programma TrueType è incorporato, il CIDFont di Tipo 2 mappa gli identificatori di carattere agli indici di glifo tramite la voce CIDToGIDMap — ISO 32000-2 §9 (, il digest fissato dalla pagina del contratto B1). Il subsetter preserva con precisione la numerazione originale dei glifi, così un /CIDToGIDMap /Identity resta valido per il subset. CjkFontValidator è la diagnostica che verifica se un font candidato copre i blocchi Unicode richiesti da uno script prima che il font venga scelto.
Superficie dell’API
Sezione intitolata “Superficie dell’API”| Tipo | Genere | Membri principali | Stabilità | Da |
|---|---|---|---|---|
ShaperInterface | interface | shape(ShaperInput): ShapingResult | stabile | 3.2.0 |
ShaperFactory | final class | default(), create(), wouldUseRealShaper() | stabile | 3.2.0 |
NullShaper | final readonly class | shaper di fallback pass-through | stabile | 3.2.0 |
ShapingResult | final readonly class | $glyphRuns, $originalText, $script, $direction, $shaperImpl | stabile | 3.2.0 |
ScriptShaperRegistry | final class | registerMongolian(), getMongolian(), hasMongolian() e gli equivalenti per il tibetano | stabile | 3.1.0 |
CjkFontValidator | final class | validateCoverage(), detectScript(), isCjkCodepoint() | stabile | 1.0.0 |
Le forme register*, get* e has* di ScriptShaperRegistry e le interfacce degli shaper di script costituiscono un contratto congelato. ShapingResult è, per progettazione, l’unico output dello shaper visibile al consumer.
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Font\Shaper\ShaperFactory;use NextPDF\Font\Shaper\ShaperImpl;
$factory = ShaperFactory::default();$shaper = $factory->create();
// Branch on the result tag, not on the concrete class.$wouldShape = $factory->wouldUseRealShaper() ? 'HarfBuzz backend available' : 'NullShaper fallback (degraded — no substitution or positioning)';
echo $wouldShape, "\n";ShaperFactory::default() collega il probe delle capacità in produzione. create() memoizza il backend selezionato per l’intero ciclo di vita della factory. L’indicazione trasparente sulle capacità proviene da wouldUseRealShaper() e dal tag shaperImpl su ogni risultato.
Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Text\Shaping\MongolianShaperInterface;use NextPDF\Text\Shaping\ScriptShaperRegistry;
final readonly class ComplexScriptBootstrap{ public function __construct(private ScriptShaperRegistry $registry) {}
/** * Register a consumer-supplied Mongolian shaper provider at boot so * the layout pipeline can resolve it by ISO 15924 script tag. */ public function register(MongolianShaperInterface $mongolian): void { $this->registry->registerMongolian($mongolian); }
public function hasMongolian(): bool { return $this->registry->hasMongolian(); }}Il registry è il punto di integrazione per i provider di script complessi. Il motore fornisce la giunzione e la forma congelata degli accessor. Le implementazioni per mongolo e tibetano sono fornite dal consumer.
Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Un risultato di
NullShaperha avanzamenti pari a zero e offset pari a zero. Non immettere direttamente tali posizioni in un layout di testo: risolvere gli avanzamenti dal modulo delle metriche dei font e rilevare il fallback tramite il tagshaperImpl. - Un input vuoto produce un elenco
glyphRunsvuoto, non una run vuota. Il codice di iterazione del consumer non richiede un caso speciale per le run di lunghezza zero. ScriptShaperRegistrynon implementa direttamentePsr\Container\ContainerInterface, in modo che gli accessor tipizzati mantengano il loro tipo di ritorno ristretto nell’analisi statica. UsaregetMongolian()egetTibetan(), non unget()generico.- I tag di script vengono confrontati in base al valore alpha-4 canonico ISO 15924, memorizzato senza distinzione tra maiuscole e minuscole. Passare
MongoTibt. L’uso di maiuscole o minuscole non influisce sulla ricerca. - I caratteri della CJK Extension B risiedono nel piano 2 di Unicode e impongono una subtable cmap di Formato 12 nel subset. Il percorso di codifica gestisce questo caso. Non dare per scontato che il piano multilingue di base esaurisca il discorso sul CJK.
Prestazioni
Sezione intitolata “Prestazioni”Il probe delle capacità viene eseguito una sola volta per istanza di ShaperFactory e il backend viene memoizzato, quindi le chiamate ripetute a create() sono gratuite. NullShaper è lineare rispetto al numero di codepoint della run di input e non comporta I/O. La risoluzione di ScriptShaperRegistry è una ricerca per chiave a tempo costante. CjkFontValidator campiona i codepoint a intervalli anziché testarli tutti, mantenendo economici i controlli di copertura anche su un font CJK da 20,000 glifi. Il performance_budget di 1500 ms di tempo reale e 64 MB di picco copre un’esecuzione tipica. Il costo dominante nello shaping reale è il backend OpenType stesso, che resta fuori dall’ambito del processo quando il fallback è attivo.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”La giunzione dello shaper consuma una stringa UTF-8. NullShaper tollera l’UTF-8 malformato suddividendolo nel modo migliore possibile anziché generare un’eccezione, perché il contratto documentato per il fallback è già «nessuno shaping reale». Il chiamante deve essere preparato a un output di bassa qualità. Il contratto di cluster basato su offset di byte usa una lunghezza orientata ai byte, corretta per input multibyte, ed evita un difetto di mappatura dei cluster con scarto di un codepoint. Il backend reale, quando presente, è una libreria nativa di terze parti. Trattare il suo input come non attendibile e limitare a monte la lunghezza della run. Il registry degli shaper di script memorizza i provider forniti dal consumer: il confine di fiducia per tali implementazioni è quello del consumer, non quello del motore.
Conformità
Sezione intitolata “Conformità”| Asserzione | Standard | Clausola | Evidenza |
|---|---|---|---|
Un face TrueType CJK incorporato viene emesso come font di Tipo 0 con una CMap Identity-H e un discendente CIDFontType2. | ISO 32000-2 | §9.7.4 | Digest RAG troncato dal limite di licenza; prefisso 7a5258772f508e3b, vedere _downgraded-claims-o3.md |
Un CIDFont di Tipo 2 incorporato mappa gli identificatori di carattere agli indici di glifo tramite CIDToGIDMap. | ISO 32000-2 | §9 |
Entrambe le clausole sono parafrasate. La seconda è fissata tramite digest (riutilizzata dalla pagina del contratto B1) e la prima è corroborata da ADR-013 e dalla panoramica per sviluppatori del cmap-encoder. NextPDF non riproduce il testo normativo. Il backend dello shaper è indipendente dalla conformità PDF. Le asserzioni di conformità qui riportate riguardano l’emissione del dizionario dei font CJK prodotta dalla giunzione di codifica, ulteriormente documentata in ADR-013 e nella panoramica per sviluppatori del cmap-encoder.
Contesto commerciale
Sezione intitolata “Contesto commerciale”Una pipeline avanzata di pre-elaborazione del testo e i servizi di estrazione si basano sulla giunzione dello shaper di Core e sui tipi valore per la gestione delle run. Il modulo di testo di Core fornisce senza licenza la giunzione, il fallback e il registry degli shaper di script. L’omissione di un link di conversione è intenzionale.
Vedere anche
Sezione intitolata “Vedere anche”- Tipografia: registry, subsetting, CMap, codifica, BiDi — la giunzione di codifica e il motore BiDi.
- Font: tipi valore, embedding, fallback — il
FontInfoa cui fa riferimento l’input dello shaper. - Contracts / Typography — il contratto del pre-elaboratore di testo a monte dello shaping.