стабильность: Экспериментальная
Поддержка компоновки сложных письменностей
Подключаемое превью. Компоновка сложных письменностей по умолчанию выключена. Когда она выключена, движок рендерит через существующий путь кодовая точка → cmap — побайтово идентично сборке без этой функции. Включайте её только тогда, когда у вас есть libharfbuzz и шрифт, способный к компоновке, и проверяйте результат.
Рендерер HTML добавляет подключаемый компоновщик сложных письменностей для тибетской и монгольской. Когда компоновщик включён, обнаруженный прогон в области действия — тибетский или монгольский — компонуется через libharfbuzz и выдаётся как коды глифов Identity-H. Компоновщик покрывает горизонтальный тибетский в начертаниях TrueType и CFF/OTTO, включая перенос строк, и вертикальный монгольский, набираемый сверху вниз (TTB).
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Компоновщик поставляется в пакете core. Подключаемая опция
CssFeatureFlags::$complexTextShaping помечена @since 6.1.0. libharfbuzz —
требование времени выполнения, когда флаг включён — компоновщик вызывает
libharfbuzz через расширение PHP FFI. Когда флаг выключен, у библиотеки нет
зависимости от libharfbuzz.
Концептуальный обзор
Заголовок раздела «Концептуальный обзор»Сложные письменности переупорядочивают, подставляют и перепозиционируют глифы по контексту. Наивное отображение кодовая точка → глиф рендерит их явно неверно. Компоновщик передаёт прогон в области действия в libharfbuzz, который применяет таблицы компоновки OpenType шрифта, а движок выдаёт получившуюся последовательность глифов как составной шрифт Type 0 с кодированием Identity-H (ISO 32000-2 §9.7.4 — показываемая строка — это двухбайтовые CID).
Область действия намеренна. Компоновщик распознаёт тибетские и монгольские прогоны и компонует их; он не претендует на общее покрытие сложных письменностей. Горизонтальный тибетский компонуется в начертаниях TrueType и CFF/OTTO с переносом строк. Монгольский компонуется вертикально, сверху вниз.
Граница с отказом закрытием — жёсткая и типизированная
Заголовок раздела «Граница с отказом закрытием — жёсткая и типизированная»Компоновщик никогда не выдаёт нескомпонованные, визуально сломанные глифы как запасной вариант. Прогон, который нельзя скомпоновать точно, вместо этого вызывает типизированное исключение:
ComplexScriptShapingException— прогон нельзя скомпоновать точно: в шрифте нет нужных глифов (получился бы.notdef), начертание CFF просят компоновать по вертикальному пути, прогон содержит ссылку или монгольской колонке нужен перенос (случай вне области действия).HarfBuzzUnavailableException— флаг включён, но libharfbuzz недостижима через FFI во время выполнения.
При выключенном флаге прогон в области действия рендерится через существующий путь кодовая точка → cmap. Это задокументированное ограничение, а не заявление о компоновке: путь с выключенным флагом не применяет компоновку OpenType, поэтому контекстные формы не гарантируются. Не описывайте вывод этого пути как «скомпонованный».
Граница честности — объективный паритет, а не эстетическое одобрение
Заголовок раздела «Граница честности — объективный паритет, а не эстетическое одобрение»Точность компоновки проверяется объективно относительно HarfBuzz: идентификаторы выдаваемых глифов, отображение кластеров и позиции глифов совпадают с эталонным выводом HarfBuzz (паритет по глифу, кластеру и позиции). Эстетическая проверка носителем языка — оценка того, читается ли результат естественно для свободно владеющего читателя, — это отслеживаемое продолжение после выпуска. NextPDF не делает никакого заявления о языковом качестве в этом API или в этих документах. Объективный паритет утверждается; эстетическое качество — нет.
Поверхность API
Заголовок раздела «Поверхность API»| Символ | Расположение | Роль |
|---|---|---|
CssFeatureFlags::$complexTextShaping | src/Html/CssFeatureFlags.php | Подключаемый флаг для тибетского/монгольского компоновщика (по умолчанию false). |
Config::withCssFeatureFlags(CssFeatureFlags $flags): self | src/Core/Config.php | Присоединяет набор флагов к конфигурации документа. |
ComplexScriptShapingException | src/Font/Shaper/ComplexScriptShapingException.php | Выбрасывается, когда прогон в области действия нельзя скомпоновать точно. |
HarfBuzzUnavailableException | src/Font/Shaper/HarfBuzzUnavailableException.php | Выбрасывается, когда флаг включён, но libharfbuzz недоступна. |
Пример кода — Быстрый старт
Заголовок раздела «Пример кода — Быстрый старт»<?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');Пример кода — Продакшен
Заголовок раздела «Пример кода — Продакшен»Зарегистрируйте шрифт, способный к компоновке, подключите компоновщик и явно обработайте два типизированных режима отказа. Точный рендеринг или ясное исключение — но никогда молча сломанный прогон глифов.
<?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 требуется, когда включено. При включённом флаге и отсутствующей
libharfbuzz движок выбрасывает
HarfBuzzUnavailableException. Он не деградирует молча. - Выключено — это не «скомпоновано». При выключенном флаге прогон в области действия рендерится через путь cmap без компоновки OpenType. Это задокументированное ограничение; не называйте это скомпонованным выводом.
- Область действия — тибетская и монгольская. Другие сложные письменности вне области этого слоя.
- Ссылка в прогоне отказывает закрытием. Прогон, содержащий аннотацию-ссылку,
вызывает
ComplexScriptShapingException, потому что прямоугольник ссылки не может следовать за переупорядочением при компоновке. - Нет заявления о языковом качестве. Паритет с HarfBuzz утверждается; эстетическое качество для носителя языка — отслеживаемое продолжение и не заявляется.
Производительность
Заголовок раздела «Производительность»Компоновка добавляет один вызов libharfbuzz на прогон в области действия плюс
проход выдачи глифов, линейный по числу глифов. Бюджет (wall_ms: 2000,
peak_mb: 128) следует профилю CJK/сложных письменностей, потому что шрифты для
компоновки велики и обработка шрифта доминирует в стоимости.
Заметки по безопасности
Заголовок раздела «Заметки по безопасности»Включение компоновщика вводит вызов FFI в libharfbuzz, нативную библиотеку. Файлы шрифтов остаются недоверенным бинарным вводом, обрабатываемым существующей валидацией слоя типографики, прежде чем они достигают компоновщика. Компоновщик потребляет уже зарегистрированные, уже проверенные начертания. Считайте происхождение шрифтов, предоставленных конечным пользователем, недоверенным и предоставляйте libharfbuzz из доверенного источника.
Соответствие стандартам
Заголовок раздела «Соответствие стандартам»| Утверждение | Спецификация | Раздел |
|---|---|---|
| Скомпонованные прогоны выдаются как двухбайтовые CID Identity-H в составном шрифте Type 0. | ISO 32000-2 | §9.7.4 |
| Компоновщик применяет подстановку и позиционирование глифов OpenType шрифта. | OpenType Specification | GSUB / GPOS |
| Формирование кластеров следует свойствам письменности для тибетской и монгольской. | Unicode Standard Annex | Tibetan and Mongolian |
Это превью-реализация, ограниченная тибетской и монгольской, проверенная на объективный паритет с HarfBuzz. Она не делает заявления о языковом качестве и не утверждает сквозное соответствие PDF для созданного файла. Текст стандартов не воспроизводится.