stabilità: Sperimentale
Supporto dello shaping di script complessi
In sintesi
Sezione intitolata “In sintesi”Anteprima opt-in. Lo shaping di script complessi è disattivato per impostazione predefinita. Quando è spento, il motore rende attraverso il percorso esistente da codepoint a cmap — byte-identico a una build senza la funzionalità. Attivalo solo quando hai libharfbuzz e un font capace di shaping, e convalida il risultato.
Il renderer HTML aggiunge uno shaper opt-in di script complessi per tibetano e mongolo. Quando lo shaper è attivo, un tratto tibetano o mongolo in ambito rilevato è sottoposto a shaping tramite libharfbuzz ed emesso come codici di glifo Identity-H. Lo shaper copre il tibetano orizzontale nei caratteri TrueType e CFF/OTTO, incluso l’a capo, e il mongolo verticale impostato dall’alto verso il basso (TTB).
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Lo shaper è incluso nel pacchetto core. L’opt-in
CssFeatureFlags::$complexTextShaping è @since 6.1.0. libharfbuzz è un
requisito di runtime quando il flag è attivo — lo shaper chiama in libharfbuzz
attraverso l’estensione FFI di PHP. Quando il flag è spento, la libreria non ha
alcuna dipendenza da libharfbuzz.
Panoramica concettuale
Sezione intitolata “Panoramica concettuale”Gli script complessi riordinano, sostituiscono e riposizionano i glifi in base al contesto. Una mappatura ingenua da codepoint a glifo li rende visibilmente errati. Lo shaper consegna un tratto in ambito a libharfbuzz, che applica le tabelle di shaping OpenType del font, e il motore emette la sequenza di glifi risultante come un font composito Type 0 con codifica Identity-H (ISO 32000-2 §9.7.4 — la stringa mostrata è composta da CID a due byte).
L’ambito è deliberato. Lo shaper riconosce i tratti tibetani e mongoli e li sottopone a shaping; non rivendica una copertura generale di script complessi. Il tibetano orizzontale è sottoposto a shaping nei caratteri TrueType e CFF/OTTO, con a capo di riga. Il mongolo è sottoposto a shaping verticalmente, dall’alto verso il basso.
Confine fail-closed — netto e tipizzato
Sezione intitolata “Confine fail-closed — netto e tipizzato”Lo shaper non emette mai come fallback glifi non sottoposti a shaping e visivamente rotti. Un tratto che non può essere sottoposto a shaping fedelmente solleva invece un’eccezione tipizzata:
ComplexScriptShapingException— il tratto non può essere sottoposto a shaping fedelmente: al font mancano i glifi necessari (ne risulterebbe un.notdef), a un carattere CFF viene chiesto di eseguire lo shaping nel percorso verticale, il tratto contiene un link, oppure una colonna mongola necessita di a capo (un caso fuori ambito).HarfBuzzUnavailableException— il flag è attivo ma libharfbuzz non è raggiungibile tramite FFI a runtime.
Con il flag spento, un tratto in ambito viene reso attraverso il percorso esistente da codepoint a cmap. Questa è una limitazione documentata, non una rivendicazione di shaping: il percorso spento non applica lo shaping OpenType, perciò le forme contestuali non sono garantite. Non descrivere l’output del percorso spento come “sottoposto a shaping”.
Confine di onestà — parità oggettiva, non approvazione estetica
Sezione intitolata “Confine di onestà — parità oggettiva, non approvazione estetica”La fedeltà di shaping è convalidata oggettivamente rispetto a HarfBuzz: gli identificatori di glifo emessi, la mappatura dei cluster e le posizioni dei glifi corrispondono all’output di riferimento di HarfBuzz (parità di glifo, cluster e posizione). Una revisione estetica da parte di un madrelingua — che giudica se il risultato si legge in modo naturale per un lettore fluente — è un seguito tracciato post-rilascio. NextPDF non avanza alcuna rivendicazione di qualità linguistica in questa API o in questa documentazione. La parità oggettiva è asserita; la qualità estetica no.
Superficie API
Sezione intitolata “Superficie API”| Simbolo | Posizione | Ruolo |
|---|---|---|
CssFeatureFlags::$complexTextShaping | src/Html/CssFeatureFlags.php | Flag opt-in per lo shaper tibetano/mongolo (predefinito false). |
Config::withCssFeatureFlags(CssFeatureFlags $flags): self | src/Core/Config.php | Collega l’insieme di flag alla configurazione di un documento. |
ComplexScriptShapingException | src/Font/Shaper/ComplexScriptShapingException.php | Sollevata quando un tratto in ambito non può essere sottoposto a shaping fedelmente. |
HarfBuzzUnavailableException | src/Font/Shaper/HarfBuzzUnavailableException.php | Sollevata quando il flag è attivo ma libharfbuzz non è disponibile. |
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\Core\Config;use NextPDF\Core\Document;use NextPDF\Html\Css\CssFeatureFlags;
$config = (new Config())->withCssFeatureFlags( new CssFeatureFlags(complexTextShaping: true),);
$doc = Document::createStandalone($config);$doc->addPage();$doc->writeHtml( '<div style="font-family: NotoSerifTibetan;">བོད་སྐད་</div>',);$doc->save(__DIR__ . '/tibetan.pdf');Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”Registra un font capace di shaping, fai opt-in nello shaper e gestisci esplicitamente le due modalità di fallimento tipizzate. Un render fedele o un’eccezione chiara — mai un tratto di glifi rotto silenziosamente.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\DocumentFactory;use NextPDF\Exception\ComplexScriptShapingException;use NextPDF\Exception\HarfBuzzUnavailableException;use NextPDF\Graphics\ImageRegistry;use NextPDF\Html\Css\CssFeatureFlags;use NextPDF\Typography\FontRegistry;
$fontRegistry = new FontRegistry();$fontRegistry->register('/path/to/NotoSerifTibetan-Regular.ttf', alias: 'NotoSerifTibetan');
$config = (new Config())->withCssFeatureFlags( new CssFeatureFlags(complexTextShaping: true),);
$factory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));$doc = $factory->create($config);$doc->setLanguage('bo');$doc->addPage();
try { $doc->writeHtml('<div style="font-family: NotoSerifTibetan;">བོད་སྐད་</div>');} catch (HarfBuzzUnavailableException $e) { // The flag is on but libharfbuzz is not reachable. Install it, or turn the // flag off to fall back to the unshaped cmap path. throw $e;} catch (ComplexScriptShapingException $e) { // The run cannot be shaped faithfully (missing glyphs, link in run, // out-of-scope case). Fix the font or the content; do not ship broken glyphs. throw $e;}
$doc->save($out);Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- libharfbuzz è richiesto quando è attivo. Con il flag attivo e libharfbuzz
assente, il motore solleva
HarfBuzzUnavailableException. Non degrada silenziosamente. - Spento non significa “sottoposto a shaping”. Con il flag spento, un tratto in ambito viene reso attraverso il percorso cmap senza shaping OpenType. Questa è una limitazione documentata; non chiamarla output sottoposto a shaping.
- L’ambito è tibetano e mongolo. Altri script complessi sono fuori ambito per questa fetta.
- Un link nel tratto fallisce in modo fail-closed. Un tratto che contiene
un’annotazione di link solleva
ComplexScriptShapingException, perché il rettangolo del link non può seguire il riordino di shaping. - Nessuna rivendicazione di qualità linguistica. La parità con HarfBuzz è asserita; la qualità estetica da parte di un madrelingua è un seguito tracciato e non è rivendicata.
Prestazioni
Sezione intitolata “Prestazioni”Lo shaping aggiunge una chiamata a libharfbuzz per ogni tratto in ambito, più il
passaggio di emissione dei glifi, lineare nel conteggio dei glifi. Il budget
(wall_ms: 2000, peak_mb: 128) segue il profilo CJK/script complessi, perché i
font di shaping sono grandi e la gestione del font domina il costo.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”Abilitare lo shaper introduce una chiamata FFI in libharfbuzz, una libreria nativa. I file di font restano input binario non attendibile gestito dalla convalida esistente del livello tipografico prima di raggiungere lo shaper. Lo shaper consuma caratteri già registrati e già convalidati. Tratta la provenienza dei font forniti dall’utente finale come non attendibile e fornisci libharfbuzz da una fonte attendibile.
Conformità
Sezione intitolata “Conformità”| Affermazione | Standard | Clausola |
|---|---|---|
| I tratti sottoposti a shaping sono emessi come CID a due byte Identity-H in un font composito Type 0. | ISO 32000-2 | §9.7.4 |
| Lo shaper applica la sostituzione e il posizionamento dei glifi OpenType del font. | OpenType Specification | GSUB / GPOS |
| La formazione dei cluster segue le proprietà di script per tibetano e mongolo. | Unicode Standard Annex | Tibetan and Mongolian |
Questa è un’implementazione di anteprima limitata a tibetano e mongolo, convalidata per la parità oggettiva con HarfBuzz. Non avanza alcuna rivendicazione di qualità linguistica e non asserisce alcuna conformità PDF end-to-end per il file prodotto. Nessun testo normativo è riprodotto.