stabilité: Expérimental
Prise en charge du façonnage des écritures complexes
Prévisualisation opt-in. Le façonnage des écritures complexes est désactivé par défaut. Lorsqu’il est désactivé, le moteur effectue le rendu via le chemin codepoint-vers-cmap existant — octet pour octet identique à une build sans la fonctionnalité. Ne l’activez que lorsque vous disposez de libharfbuzz et d’une police capable de façonnage, et validez le résultat.
Le moteur de rendu HTML ajoute un façonneur d’écritures complexes opt-in pour le tibétain et le mongol. Lorsque le façonneur est activé, une séquence tibétaine ou mongole détectée dans le périmètre est façonnée via libharfbuzz et émise sous forme de codes de glyphe Identity-H. Le façonneur couvre le tibétain horizontal dans les fontes TrueType et CFF/OTTO, y compris le renvoi à la ligne, et le mongol vertical disposé de haut en bas (TTB).
Installation
Section intitulée « Installation »composer require nextpdf/core:^3Le façonneur est livré dans le paquet core. L’opt-in
CssFeatureFlags::$complexTextShaping est @since 6.1.0. libharfbuzz est une
exigence d’exécution lorsque l’indicateur est activé — le façonneur appelle
libharfbuzz via l’extension FFI de PHP. Lorsque l’indicateur est désactivé, la
bibliothèque n’a aucune dépendance à libharfbuzz.
Aperçu conceptuel
Section intitulée « Aperçu conceptuel »Les écritures complexes réordonnent, substituent et repositionnent les glyphes selon le contexte. Une correspondance codepoint-vers-glyphe naïve les rend visiblement de façon incorrecte. Le façonneur remet une séquence dans le périmètre à libharfbuzz, qui applique les tables de façonnage OpenType de la police, et le moteur émet la séquence de glyphes résultante sous forme de police composite Type 0 avec encodage Identity-H (ISO 32000-2 §9.7.4 — la chaîne affichée est constituée de CID sur deux octets).
Le périmètre est délibéré. Le façonneur reconnaît les séquences tibétaines et mongoles et les façonne ; il ne revendique pas une couverture générale des écritures complexes. Le tibétain horizontal est façonné dans les fontes TrueType et CFF/OTTO, avec renvoi à la ligne. Le mongol est façonné verticalement, de haut en bas.
Frontière fail-closed — stricte et typée
Section intitulée « Frontière fail-closed — stricte et typée »Le façonneur n’émet jamais de glyphes non façonnés et visuellement cassés comme repli. Une séquence qui ne peut pas être façonnée fidèlement lève plutôt une exception typée :
ComplexScriptShapingException— la séquence ne peut pas être façonnée fidèlement : la police ne possède pas les glyphes nécessaires (un.notdefen résulterait), une fonte CFF est sollicitée pour façonner dans le chemin vertical, la séquence contient un lien, ou une colonne mongole a besoin d’un renvoi à la ligne (un cas hors périmètre).HarfBuzzUnavailableException— l’indicateur est activé mais libharfbuzz n’est pas joignable via FFI à l’exécution.
Avec l’indicateur désactivé, une séquence dans le périmètre est rendue via le chemin codepoint-vers-cmap existant. C’est une limitation documentée, pas une revendication de façonnage : le chemin désactivé n’applique pas de façonnage OpenType, de sorte que les formes contextuelles ne sont pas garanties. Ne décrivez pas la sortie du chemin désactivé comme « façonnée ».
Frontière d’honnêteté — parité objective, pas validation esthétique
Section intitulée « Frontière d’honnêteté — parité objective, pas validation esthétique »La fidélité de façonnage est validée objectivement par rapport à HarfBuzz : les identifiants de glyphe émis, la cartographie des clusters et les positions de glyphe correspondent à la sortie de référence HarfBuzz (parité de glyphe, de cluster et de position). Une revue esthétique par un locuteur natif — jugeant si le résultat se lit naturellement pour un lecteur courant — est un suivi post-livraison consigné. NextPDF ne fait aucune revendication de qualité linguistique dans cette API ni dans cette documentation. La parité objective est affirmée ; la qualité esthétique ne l’est pas.
Surface d’API
Section intitulée « Surface d’API »| Symbole | Emplacement | Rôle |
|---|---|---|
CssFeatureFlags::$complexTextShaping | src/Html/CssFeatureFlags.php | Indicateur opt-in pour le façonneur tibétain/mongol (par défaut false). |
Config::withCssFeatureFlags(CssFeatureFlags $flags): self | src/Core/Config.php | Attache l’ensemble d’indicateurs à une configuration de document. |
ComplexScriptShapingException | src/Font/Shaper/ComplexScriptShapingException.php | Levée lorsqu’une séquence dans le périmètre ne peut pas être façonnée fidèlement. |
HarfBuzzUnavailableException | src/Font/Shaper/HarfBuzzUnavailableException.php | Levée lorsque l’indicateur est activé mais que libharfbuzz est indisponible. |
Exemple de code — Démarrage rapide
Section intitulée « Exemple de code — Démarrage rapide »<?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');Exemple de code — Production
Section intitulée « Exemple de code — Production »Enregistrez une police capable de façonnage, activez le façonneur, et traitez explicitement les deux modes de défaillance typés. Un rendu fidèle ou une exception claire — jamais une séquence de glyphes silencieusement cassée.
<?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);Cas limites et pièges
Section intitulée « Cas limites et pièges »- libharfbuzz est requis lorsque c’est activé. Avec l’indicateur activé et
libharfbuzz absent, le moteur lève
HarfBuzzUnavailableException. Il ne se dégrade pas silencieusement. - Le mode désactivé n’est pas « façonné ». Avec l’indicateur désactivé, une séquence dans le périmètre est rendue via le chemin cmap sans façonnage OpenType. C’est une limitation documentée ; ne la qualifiez pas de sortie façonnée.
- Le périmètre est le tibétain et le mongol. Les autres écritures complexes sont hors périmètre pour cette tranche.
- Un lien dans la séquence échoue en mode fail-closed. Une séquence qui
contient une annotation de lien lève
ComplexScriptShapingException, car le rectangle du lien ne peut pas suivre le réordonnancement de façonnage. - Aucune revendication de qualité linguistique. La parité avec HarfBuzz est affirmée ; la qualité esthétique par un locuteur natif est un suivi consigné et n’est pas revendiquée.
Performance
Section intitulée « Performance »Le façonnage ajoute un appel libharfbuzz par séquence dans le périmètre, plus la
passe d’émission de glyphes, linéaire en nombre de glyphes. Le budget
(wall_ms: 2000, peak_mb: 128) suit le profil CJK/écritures complexes, car les
polices de façonnage sont volumineuses et le traitement de police domine le coût.
Notes de sécurité
Section intitulée « Notes de sécurité »L’activation du façonneur introduit un appel FFI vers libharfbuzz, une bibliothèque native. Les fichiers de police restent une entrée binaire non fiable traitée par la validation existante de la couche typographique avant qu’ils n’atteignent le façonneur. Le façonneur consomme des fontes déjà enregistrées et déjà validées. Traitez la provenance des polices fournies par l’utilisateur final comme non fiable, et approvisionnez libharfbuzz depuis une source de confiance.
Conformité
Section intitulée « Conformité »| Énoncé | Spécification | Clause |
|---|---|---|
| Les séquences façonnées sont émises sous forme de CID Identity-H sur deux octets dans une police composite Type 0. | ISO 32000-2 | §9.7.4 |
| Le façonneur applique la substitution et le positionnement de glyphes OpenType de la police. | OpenType Specification | GSUB / GPOS |
| La formation de clusters suit les propriétés d’écriture pour le tibétain et le mongol. | Unicode Standard Annex | Tibetan and Mongolian |
Il s’agit d’une implémentation de prévisualisation cantonnée au tibétain et au mongol, validée pour la parité objective avec HarfBuzz. Elle ne fait aucune revendication de qualité linguistique et n’affirme aucune conformité PDF de bout en bout pour le fichier produit. Aucun texte de norme n’est reproduit.