estabilidade: Experimental
Suporte a composição de scripts complexos
Visão geral
Seção intitulada “Visão geral”Pré-visualização opcional. A composição de scripts complexos é desativada por padrão. Quando está desativada, o motor renderiza pelo caminho existente de codepoint para cmap — idêntico byte a byte à de uma compilação sem o recurso. Ative-a somente quando você tiver o libharfbuzz e uma fonte capaz de composição, e valide o resultado.
O renderizador HTML adiciona um compositor de scripts complexos opcional para tibetano e mongol. Quando o compositor está ativado, uma sequência em tibetano ou mongol detectada no escopo é composta através do libharfbuzz e emitida como códigos de glifo Identity-H. O compositor cobre tibetano horizontal em faces TrueType e CFF/OTTO, incluindo quebra de linha, e mongol vertical disposto de cima para baixo (TTB).
Instalação
Seção intitulada “Instalação”composer require nextpdf/core:^3O compositor é entregue no pacote core. O recurso opcional
CssFeatureFlags::$complexTextShaping é @since 6.1.0. O libharfbuzz é um
requisito de runtime quando a flag está ativada — o compositor chama o
libharfbuzz através da extensão FFI do PHP. Quando a flag está desativada, a
biblioteca não tem dependência de libharfbuzz.
Visão geral conceitual
Seção intitulada “Visão geral conceitual”Scripts complexos reordenam, substituem e reposicionam glifos conforme o contexto. Um mapeamento ingênuo de codepoint para glifo os renderiza visivelmente errados. O compositor entrega uma sequência no escopo ao libharfbuzz, que aplica as tabelas de composição OpenType da fonte, e o motor emite a sequência de glifos resultante como uma fonte composta Type 0 com codificação Identity-H (ISO 32000-2 §9.7.4 — a string exibida é de CIDs de dois bytes).
O escopo é deliberado. O compositor reconhece sequências em tibetano e mongol e as compõe; ele não reivindica cobertura geral de scripts complexos. O tibetano horizontal é composto em faces TrueType e CFF/OTTO, com quebra de linha. O mongol é composto verticalmente, de cima para baixo.
Limite de falha fechada — rígido e tipado
Seção intitulada “Limite de falha fechada — rígido e tipado”O compositor nunca emite glifos não compostos e visualmente quebrados como fallback. Uma sequência que não pode ser composta fielmente levanta uma exceção tipada em vez disso:
ComplexScriptShapingException— a sequência não pode ser composta fielmente: a fonte não tem os glifos necessários (resultaria um.notdef), pede-se a uma face CFF que componha no caminho vertical, a sequência contém um link ou uma coluna mongol precisa de quebra de linha (um caso fora do escopo).HarfBuzzUnavailableException— a flag está ativada, mas o libharfbuzz não é alcançável por FFI em runtime.
Com a flag desativada, uma sequência no escopo é renderizada pelo caminho existente de codepoint para cmap. Essa é uma limitação documentada, não uma reivindicação de composição: o caminho desativado não aplica composição OpenType, então as formas contextuais não são garantidas. Não descreva a saída do caminho desativado como “composta”.
Limite de honestidade — paridade objetiva, não aval estético
Seção intitulada “Limite de honestidade — paridade objetiva, não aval estético”A fidelidade de composição é validada objetivamente contra o HarfBuzz: os identificadores de glifo emitidos, o mapeamento de cluster e as posições de glifo correspondem à saída de referência do HarfBuzz (paridade de glifo, cluster e posição). Uma revisão estética por falante nativo — julgando se o resultado é lido naturalmente por um leitor fluente — é um acompanhamento pós-lançamento rastreado. O NextPDF não faz nenhuma reivindicação de qualidade de idioma nesta API nem nesta documentação. A paridade objetiva é afirmada; a qualidade estética não.
Superfície da API
Seção intitulada “Superfície da API”| Símbolo | Localização | Função |
|---|---|---|
CssFeatureFlags::$complexTextShaping | src/Html/CssFeatureFlags.php | Flag opcional para o compositor de tibetano/mongol (padrão false). |
Config::withCssFeatureFlags(CssFeatureFlags $flags): self | src/Core/Config.php | Anexa o conjunto de flags a uma configuração de documento. |
ComplexScriptShapingException | src/Font/Shaper/ComplexScriptShapingException.php | Lançada quando uma sequência no escopo não pode ser composta fielmente. |
HarfBuzzUnavailableException | src/Font/Shaper/HarfBuzzUnavailableException.php | Lançada quando a flag está ativada, mas o libharfbuzz está indisponível. |
Exemplo de código — Início rápido
Seção intitulada “Exemplo de código — Início rápido”<?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');Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”Registre uma fonte capaz de composição, opte pelo compositor e trate os dois modos de falha tipados explicitamente. Uma renderização fiel ou uma exceção clara — nunca uma sequência de glifos silenciosamente quebrada.
<?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);Casos extremos e pegadinhas
Seção intitulada “Casos extremos e pegadinhas”- O libharfbuzz é obrigatório quando ativado. Com a flag ativada e o
libharfbuzz ausente, o motor lança
HarfBuzzUnavailableException. Ele não degrada silenciosamente. - Desativado não é “composto”. Com a flag desativada, uma sequência no escopo é renderizada pelo caminho de cmap sem composição OpenType. Essa é uma limitação documentada; não a chame de saída composta.
- O escopo é tibetano e mongol. Outros scripts complexos estão fora do escopo desta fatia.
- Um link na sequência falha fechado. Uma sequência que contém uma anotação
de link levanta
ComplexScriptShapingException, porque o retângulo do link não pode acompanhar a reordenação composta. - Nenhuma reivindicação de qualidade de idioma. A paridade com o HarfBuzz é afirmada; a qualidade estética por falante nativo é um acompanhamento rastreado e não é reivindicada.
Desempenho
Seção intitulada “Desempenho”A composição adiciona uma chamada ao libharfbuzz por sequência no escopo, mais a
passada de emissão de glifos, linear na contagem de glifos. O orçamento
(wall_ms: 2000, peak_mb: 128) segue o perfil CJK/scripts complexos, porque as
fontes de composição são grandes e o manuseio de fonte domina o custo.
Notas de segurança
Seção intitulada “Notas de segurança”Ativar o compositor introduz uma chamada FFI para o libharfbuzz, uma biblioteca nativa. Os arquivos de fonte permanecem como entrada binária não confiável tratada pela validação existente da camada de tipografia antes de chegarem ao compositor. O compositor consome faces já registradas e já validadas. Trate a procedência de fontes fornecidas por usuário final como não confiável e provisione o libharfbuzz a partir de uma fonte confiável.
Conformidade
Seção intitulada “Conformidade”| Declaração | Especificação | Cláusula |
|---|---|---|
| Sequências compostas são emitidas como CIDs de dois bytes Identity-H em uma fonte composta Type 0. | ISO 32000-2 | §9.7.4 |
| O compositor aplica a substituição e o posicionamento de glifos OpenType da fonte. | OpenType Specification | GSUB / GPOS |
| A formação de clusters segue as propriedades de script para tibetano e mongol. | Unicode Standard Annex | Tibetan and Mongolian |
Esta é uma implementação de pré-visualização limitada a tibetano e mongol, validada quanto à paridade objetiva com o HarfBuzz. Ela não faz nenhuma reivindicação de qualidade de idioma e não afirma nenhuma conformidade PDF de ponta a ponta para o arquivo produzido. Nenhum texto de norma é reproduzido.