Pular para o conteúdo

Crie camadas de conteúdo opcional (OCG)

Envolva o conteúdo em grupos de conteúdo opcional (OCGs) nomeados, frequentemente chamados de camadas. Um leitor de PDF pode alternar cada camada no painel de camadas, e você pode deixar uma camada oculta por padrão. Esta receita segue examples/26-layers.php.

Um OCG é um dicionário de grupo de conteúdo opcional definido pelo ISO 32000-2 com Type /OCG. O NextPDF delimita o conteúdo em camadas entre BDC/EMC e usa a tag de conteúdo marcado OC.

Terminal window
composer require nextpdf/core:^3

Você não precisa de nenhuma extensão opcional. A API de camadas é estável desde a 1.0.0 e roda na matriz de backport 8.1–8.4.

startLayer($name, $visible) abre um OCG. Tudo o que você desenhar até chamar o endLayer() correspondente pertence a esse grupo. $name é o rótulo que o leitor de PDF exibe no painel de camadas. O ISO 32000-2 exige o Name do OCG, a string exibida para quem lê o PDF. Passar $visible: false registra o grupo no estado OFF da configuração padrão; assim, o leitor o oculta até que você o ative.

A visibilidade depende da cooperação do leitor. Para um dicionário de associação de conteúdo opcional (OCMD), a política de visibilidade padrão é AnyOn. A camada fica visível se qualquer grupo referenciado estiver ON. Uma camada oculta permanece oculta apenas por convenção do leitor. Ela não é removida nem protegida, e não funciona como redação nem como controle de segurança. Para remover conteúdo, não o desenhe.

O PHPDoc gera automaticamente a superfície da API. Esta receita usa dois métodos:

  • startLayer(string $name, bool $visible = true): static — abre um OCG nomeado; $visible: false deixa a camada oculta por padrão.
  • endLayer(): static — fecha a camada aberta mais recentemente (balanceada com startLayer()).
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->startLayer('Content', visible: true);
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 8, 'Always-visible body content.', newLine: true);
$doc->endLayer();
$doc->startLayer('Debug Grid', visible: false); // hidden until toggled
$doc->setDrawColor(200, 200, 200);
for ($x = 0.0; $x <= 210.0; $x += 10.0) {
$doc->line($x, 0, $x, 297);
}
$doc->endLayer();
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf');

Use este exemplo completo, pronto para a estrutura de testes (harness). Ele respeita NEXTPDF_COOKBOOK_OUTPUT e não adiciona entropia própria.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Layer Examples (OCG)');
$doc->addPage();
// Layer 1 — background, visible by default.
$doc->startLayer('Background', visible: true);
$doc->setFillColor(230, 240, 250);
$doc->rect(10, 10, 190, 277, 'F');
$doc->endLayer();
// Layer 2 — watermark, visible by default; can be toggled off.
$doc->startLayer('Watermark', visible: true);
$doc->setFont('helvetica', 'B', 54);
$doc->setTextColor(200, 200, 200);
$doc->startTransform();
$doc->rotate(45, 105, 148);
$doc->setXY(30, 135);
$doc->cell(150, 20, 'DRAFT', align: Alignment::Center);
$doc->stopTransform();
$doc->endLayer();
// Layer 3 — main content, visible by default.
$doc->startLayer('Content', visible: true);
$doc->setTextColor(0);
$doc->setFont('helvetica', 'B', 20);
$doc->setXY(10, 15);
$doc->cell(0, 14, 'Layer Examples (OCG)', newLine: true);
$doc->ln(4);
$doc->setFont('helvetica', '', 11);
$doc->multiCell(0, 7, 'This document contains four optional content groups. '
. "Toggle them in your reader's Layers panel.");
$doc->endLayer();
// Layer 4 — debug grid, hidden by default.
$doc->startLayer('Debug Grid', visible: false);
$doc->setDrawColor(180, 180, 180);
$doc->setLineWidth(0.15);
for ($x = 0.0; $x <= 210.0; $x += 10.0) {
$doc->line($x, 0, $x, 297);
}
for ($y = 0.0; $y <= 297.0; $y += 10.0) {
$doc->line(0, $y, 210, $y);
}
$doc->endLayer();
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf';
$doc->save($out);
echo "Created layers.pdf\n";
  • Balanceie cada startLayer() com um endLayer(). Uma camada não fechada deixa um BDC pendente, sem EMC correspondente, e torna a estrutura do documento malformada. Emparelhe cada chamada de abertura com a respectiva chamada de fechamento.
  • Uma camada oculta não é removida. visible: false oculta o conteúdo apenas por convenção do leitor. As marcas e qualquer texto permanecem no arquivo e são recuperáveis. Isso não é um recurso de redação. Para dados sensíveis, não os desenhe.
  • O suporte ao painel de camadas varia. Alternar exige um leitor que exponha o conteúdo opcional. Pipelines de impressão e visualizadores mínimos podem mostrar sempre, ou ocultar sempre, camadas desativadas por padrão.
  • Aninhamento. Camadas aninhadas são permitidas, mas a visibilidade de cada grupo interno permanece independente. Não presuma que uma camada externa em OFF oculta um grupo interno em ON, a menos que você configure uma política de associação.

Cada camada adiciona um dicionário OCG e um par BDC/EMC ao redor das respectivas marcações. O custo adicional é mínimo. O custo escala com o conteúdo dentro das camadas, não com o número de camadas; por isso, permanece bem dentro do orçamento de 2000 ms / 64 MB.

A visibilidade do conteúdo opcional depende da cooperação do leitor, não é um controle de acesso. Ocultar uma camada não criptografa, não redige nem remove o conteúdo dela. Qualquer pessoa pode reativar a camada ou extrair os bytes. Nunca use uma camada oculta para esconder texto confidencial; em vez disso, omita o conteúdo por completo. Esta receita não processa nenhuma entrada nem faz requisições de rede.

DeclaraçãoEspecificaçãoCláusulareference_id
Um dicionário OCG tem Type /OCG.ISO 32000-2§8.11.2
O Name do OCG é o rótulo obrigatório exibido para quem lê o PDF.ISO 32000-2§8.11.2
O conteúdo opcional é delimitado entre BDC/EMC com a tag OC.ISO 32000-2§8.11.3.2
As políticas de OCMD são AllOn/AnyOn/AnyOff/AllOff (padrão AnyOn).ISO 32000-2§8.11.4.3

Perfil de reprodutibilidade — estrutural. O /ID do trailer e os átomos de data mudam a cada salvamento. A estrutura de testes (harness) remove esses átomos e compara a estrutura normalizada pelo qpdf. Esta receita descreve como o NextPDF produz essa estrutura. Ela não afirma conformidade geral com o ISO 32000-2.

Não se aplica. Os grupos de conteúdo opcional são um recurso do Core, sem restrição do Premium.