跳转到内容
getnextpdf.com

稳定性: 实验性

CJK 竖排书写支持

可选启用的预览。 竖排组合器默认关闭。当它关闭时,引擎会与之前完全一样地水平渲染——字节完全一致。只为那些确实需要真正竖排行的文档开启它,并验证结果。

HTML 渲染器为 CSS 书写模式 writing-mode: vertical-lrwriting-mode: vertical-rl 新增了一个真正的竖排行组合器。当组合器开启时,字形会自上而下堆叠,逐字形的放置取自字体的真实竖排度量(vheavmtx 表),正如 ISO 32000-2 §9.7.5 中描述的 PDF 竖排书写模型那样。两种竖排块流方向都受支持。

Terminal window
composer require nextpdf/core:^3

该组合器随核心包一起分发。CssFeatureFlags::$layoutVerticalComposer 这个可选开关是 @since 6.1.0。引擎版本保持不变;该特性是增量式的,且默认关闭。

只有当 layoutVerticalLrlayoutVerticalComposer 都被设置时,竖排组合才会开启。在它们开启的情况下,一段 vertical-lrvertical-rl 文段会组合成一条真正的竖排行:每个字形依据其来自字体 vhea/vmtx 度量的竖排步进量来放置,而被 UAX #50 标记为竖立的字形会保持竖立。vertical-lr 自左向右排布列;vertical-rl 自右向左排布列。

这与 以 cmap 感知编码排布 CJK 文本 中记述的 cmap 感知编码外观不同,后者验证的是编码路径,但其本身并不驱动竖排书写模式。本页记述的是由书写模式可选开关启用的、布局侧的组合器。

Fail-closed 边界——它何时组合,以及在其他情况下做什么

标题为“Fail-closed 边界——它何时组合,以及在其他情况下做什么”的章节

该组合器在设计上是保守的。它只在以下条件下才将一段文段竖排组合:该文段中的每个字形都依据真实竖排度量被 UAX #50 标记为竖立,文段内没有打开的链接,且该文段是单列。当其中任何一项不成立时——标志关闭,或一段文段无法被忠实组合——引擎会回退到水平布局,并发出一个与模式匹配的推迟诊断:

  • 对于无法组合的 vertical-lr 文段,发出 HTML_WRITING_MODE_LR_DEFERRED
  • 对于无法组合的 vertical-rl 文段,发出 HTML_WRITING_MODE_RL_DEFERRED

每个诊断都携带一个 reason,因此一次推迟是可观测且可解释的,绝不会对作者要求竖排排布的文本进行沉默的水平渲染。

以下情形不在当前切片范围内,并被跟踪以备后续工作:

  • 竖排文段内被旋转(非竖立)的字形。
  • 多列竖排折行。
  • 竖排链接矩形(竖排文段内的一个链接会使该文段被推迟)。
  • 测试语料中没有捆绑的竖排度量 CJK 字体夹具,因此视觉交叉核对是被跟踪的,而非由捆绑的黄金样本断言。
符号位置角色
CssFeatureFlags::$layoutVerticalComposersrc/Html/CssFeatureFlags.php竖排行组合器的可选启用标志(默认 false)。
CssFeatureFlags::$layoutVerticalLrsrc/Html/CssFeatureFlags.phpvertical-lr 的门控;两者都须开启才能组合。
Config::withCssFeatureFlags(CssFeatureFlags $flags): selfsrc/Core/Config.php把标志集附加到一份文档配置上。

推迟诊断码 HTML_WRITING_MODE_LR_DEFERREDHTML_WRITING_MODE_RL_DEFERRED 通过渲染结果的告知通道暴露。

<?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(
layoutVerticalLr: true,
layoutVerticalComposer: true,
));
$doc = Document::createStandalone($config);
$doc->addPage();
$doc->writeHtml(
'<div style="writing-mode: vertical-rl; font-family: NotoSerifJP;">'
. '日本語の縦書き'
. '</div>',
);
$doc->save(__DIR__ . '/vertical.pdf');

一段无法被忠实组合的文段会水平渲染,并添加一个带 reasonHTML_WRITING_MODE_RL_DEFERRED 告知。在把竖排输出当作最终结果之前,请检查告知通道。

通过 DocumentFactory 注册一种携带真实竖排度量的字体,使组合器能读取 vhea/vmtx,然后把该文档接入组合器。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Html\Css\CssFeatureFlags;
use NextPDF\Typography\FontRegistry;
$fontRegistry = new FontRegistry();
$fontRegistry->register('/path/to/NotoSerifJP-Regular.otf', alias: 'NotoSerifJP');
$config = (new Config())->withCssFeatureFlags(new CssFeatureFlags(
layoutVerticalLr: true,
layoutVerticalComposer: true,
));
$factory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));
$doc = $factory->create($config);
$doc->setLanguage('ja');
$doc->addPage();
$doc->writeHtml(
'<div style="writing-mode: vertical-rl; font-family: NotoSerifJP;">'
. '縦書きの本文。'
. '</div>',
);
$doc->save($out);
  • 两个标志都必需。 组合器需要 layoutVerticalLrlayoutVerticalComposer。任一关闭,该文段都会水平渲染。
  • 真实竖排度量必需。 一种没有 vhea/vmtx 的字体无法驱动组合器;该文段会推迟到水平布局。
  • 推迟是可观测的。 一段无法组合的文段会发出带 reasonHTML_WRITING_MODE_LR_DEFERRED / HTML_WRITING_MODE_RL_DEFERRED。它绝不会沉默地横向渲染。
  • 此路径不作符合性主张。 竖排组合是一项布局能力;它不是关于所产出文件的 PDF/UA-2 或 PDF/A-4 符合性声明。符合性由检查器判定。

组合会在该文段上增加一次逐字形的竖排步进量查询,在字形数上呈线性。该预算(wall_ms: 2000peak_mb: 128)遵循 CJK 配置文件,因为竖排度量字体很大,主导成本是字体处理而非组合过程本身。

组合器从已注册、已验证的字体中读取竖排度量。它不会打开一条新的输入通道。字体文件仍然是由排版层既有校验处理的不受信任二进制输入。被组合的文本是被渲染的,而非被解释的。

主张标准条款
竖排书写使用 CIDFont 竖排字形度量进行放置。ISO 32000-2§9.7.5
writing-mode: vertical-lr / vertical-rl 设定块流方向。W3C CSS Writing Modes Level 3§3
逐字形竖立朝向遵循 Unicode 竖排朝向属性。Unicode UAX #50Vertical Orientation

这是一个单列竖立竖排子集的预览实现,并带有上述有文档记录的 fail-closed 边界。NextPDF 不断言此路径的输出符合任何配置文件;该判定由检查器作出。未重制任何标准原文。