Przejdź do głównej zawartości
getnextpdf.com

stabilność: Eksperymentalna

Obsługa kształtowania pism złożonych

Opcjonalny podgląd. Kształtowanie pism złożonych jest domyślnie wyłączone. Gdy jest wyłączone, silnik renderuje istniejącą ścieżką codepoint-to-cmap — bajtowo identycznie z kompilacją bez tej funkcji. Włączaj je tylko wtedy, gdy masz libharfbuzz i czcionkę zdolną do kształtowania, i waliduj wynik.

Renderer HTML dodaje opcjonalny shaper pism złożonych dla tybetańskiego i mongolskiego. Gdy shaper jest włączony, wykryty ciąg tybetański lub mongolski w zakresie jest kształtowany przez libharfbuzz i emitowany jako kody glifów Identity-H. Shaper obejmuje poziomy tybetański w krojach TrueType i CFF/OTTO, łącznie z zawijaniem, oraz pionowy mongolski składany z góry na dół (TTB).

Okno terminala
composer require nextpdf/core:^3

Shaper jest dostarczany w pakiecie core. Opcja CssFeatureFlags::$complexTextShaping to @since 6.1.0. libharfbuzz jest wymaganiem czasu wykonania, gdy flaga jest włączona — shaper wywołuje libharfbuzz przez rozszerzenie FFI PHP. Gdy flaga jest wyłączona, biblioteka nie ma zależności od libharfbuzz.

Pisma złożone zmieniają kolejność glifów, podstawiają je i zmieniają ich położenie zależnie od kontekstu. Naiwne mapowanie codepoint-na-glif renderuje je w widoczny sposób błędnie. Shaper przekazuje ciąg w zakresie do libharfbuzz, która stosuje tablice kształtowania OpenType czcionki, a silnik emituje wynikową sekwencję glifów jako złożoną czcionkę Type 0 z kodowaniem Identity-H (ISO 32000-2 §9.7.4 — pokazany łańcuch to dwubajtowe CID-y).

Zakres jest celowy. Shaper rozpoznaje ciągi tybetańskie i mongolskie oraz je kształtuje; nie twierdzi, że obejmuje pisma złożone ogólnie. Poziomy tybetański jest kształtowany w krojach TrueType i CFF/OTTO, z zawijaniem wierszy. Mongolski jest kształtowany pionowo, z góry na dół.

Shaper nigdy nie emituje niekształtowanych, wizualnie zepsutych glifów jako wycofania. Ciąg, którego nie da się skształtować wiernie, zgłasza zamiast tego typowany wyjątek:

  • ComplexScriptShapingException — ciągu nie da się skształtować wiernie: czcionce brakuje potrzebnych glifów (powstałby .notdef), krój CFF jest proszony o kształtowanie ścieżką pionową, ciąg zawiera łącze lub kolumna mongolska wymaga zawijania (przypadek poza zakresem).
  • HarfBuzzUnavailableException — flaga jest włączona, ale libharfbuzz nie jest osiągalny przez FFI w czasie wykonania.

Przy wyłączonej fladze ciąg w zakresie renderuje się istniejącą ścieżką codepoint-to-cmap. To udokumentowane ograniczenie, a nie twierdzenie o kształtowaniu: ścieżka wyłączona nie stosuje kształtowania OpenType, więc formy kontekstowe nie są gwarantowane. Nie opisuj wyniku ścieżki wyłączonej jako „kształtowanego”.

Granica uczciwości — obiektywna równoważność, a nie estetyczna akceptacja

Dział zatytułowany „Granica uczciwości — obiektywna równoważność, a nie estetyczna akceptacja”

Wierność kształtowania jest walidowana obiektywnie względem HarfBuzz: emitowane identyfikatory glifów, mapowanie klastrów i pozycje glifów odpowiadają referencyjnemu wynikowi HarfBuzz (równoważność glifu, klastra i pozycji). Przegląd estetyczny przez rodzimego użytkownika języka — ocena, czy wynik czyta się naturalnie dla biegłego czytelnika — jest śledzonym działaniem następczym po wydaniu. NextPDF nie wysuwa żadnego twierdzenia o jakości językowej w tym API ani w tej dokumentacji. Obiektywna równoważność jest deklarowana; jakość estetyczna nie.

SymbolLokalizacjaRola
CssFeatureFlags::$complexTextShapingsrc/Html/CssFeatureFlags.phpOpcjonalna flaga shapera tybetańsko-mongolskiego (domyślnie false).
Config::withCssFeatureFlags(CssFeatureFlags $flags): selfsrc/Core/Config.phpDołącza zestaw flag do konfiguracji dokumentu.
ComplexScriptShapingExceptionsrc/Font/Shaper/ComplexScriptShapingException.phpZgłaszany, gdy ciągu w zakresie nie da się skształtować wiernie.
HarfBuzzUnavailableExceptionsrc/Font/Shaper/HarfBuzzUnavailableException.phpZgłaszany, gdy flaga jest włączona, ale libharfbuzz jest niedostępny.
<?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');

Zarejestruj czcionkę zdolną do kształtowania, włącz shaper i obsłuż dwa typowane tryby awarii jawnie. Wierny render albo jasny wyjątek — nigdy po cichu zepsuty ciąg glifów.

<?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);
  • libharfbuzz jest wymagany, gdy włączony. Przy włączonej fladze i braku libharfbuzz silnik zgłasza HarfBuzzUnavailableException. Nie degraduje się po cichu.
  • Wyłączony to nie „kształtowany”. Przy wyłączonej fladze ciąg w zakresie renderuje się ścieżką cmap bez kształtowania OpenType. To udokumentowane ograniczenie; nie nazywaj go wynikiem kształtowanym.
  • Zakres to tybetański i mongolski. Inne pisma złożone są poza zakresem tej warstwy.
  • Łącze w ciągu kończy się niepowodzeniem fail-closed. Ciąg zawierający adnotację łącza zgłasza ComplexScriptShapingException, ponieważ prostokąt łącza nie może podążać za zmianą kolejności wynikającą z kształtowania.
  • Brak twierdzenia o jakości językowej. Równoważność z HarfBuzz jest deklarowana; estetyczna jakość w ocenie rodzimego użytkownika to śledzone działanie następcze i nie jest deklarowana.

Kształtowanie dodaje jedno wywołanie libharfbuzz na ciąg w zakresie, plus przebieg emisji glifów, liniowo względem liczby glifów. Budżet (wall_ms: 2000, peak_mb: 128) podąża za profilem CJK/pism złożonych, ponieważ czcionki do kształtowania są duże, a obsługa czcionek dominuje w koszcie.

Włączenie shapera wprowadza wywołanie FFI do libharfbuzz, biblioteki natywnej. Pliki czcionek pozostają niezaufanym wejściem binarnym obsługiwanym przez istniejącą walidację warstwy typografii, zanim dotrą do shapera. Shaper konsumuje już zarejestrowane, już zweryfikowane kroje. Traktuj pochodzenie czcionek dostarczonych przez użytkownika końcowego jako niezaufane i dostarczaj libharfbuzz z zaufanego źródła.

TwierdzenieNormaKlauzula
Kształtowane ciągi są emitowane jako dwubajtowe CID-y Identity-H w złożonej czcionce Type 0.ISO 32000-2§9.7.4
Shaper stosuje czcionkowe podstawianie i pozycjonowanie glifów OpenType.OpenType SpecificationGSUB / GPOS
Formowanie klastrów podąża za właściwościami pism dla tybetańskiego i mongolskiego.Unicode Standard AnnexTibetan and Mongolian

To podglądowa implementacja zawężona do tybetańskiego i mongolskiego, walidowana pod kątem obiektywnej równoważności z HarfBuzz. Nie wysuwa żadnego twierdzenia o jakości językowej i nie deklaruje zgodności end-to-end z PDF dla wytworzonego pliku. Nie odtwarza się żadnego tekstu normatywnego.