Salta ai contenuti

Creare livelli di contenuto opzionale (OCG)

Racchiudere i contenuti in gruppi denominati di contenuto opzionale (OCG), comunemente chiamati livelli. Il reader può attivare o disattivare ciascun livello nel relativo pannello Livelli e un livello risulta nascosto per impostazione predefinita. Questa ricetta segue examples/26-layers.php.

Un OCG è un dizionario ISO 32000-2 di gruppo di contenuto opzionale con Type /OCG. NextPDF racchiude i marcatori del livello tra BDC/EMC con il tag di contenuto marcato OC.

Terminal window
composer require nextpdf/core:^3

Non è necessaria alcuna estensione opzionale. L’API dei livelli è stabile dalla versione 1.0.0 e supporta la matrice di backport 8.1–8.4.

startLayer($name, $visible) apre un OCG. Tutto ciò che viene disegnato fino al corrispondente endLayer() appartiene a quel gruppo. $name è l’etichetta mostrata dal reader nel relativo pannello Livelli. Lo standard ISO 32000-2 rende il Name dell’OCG una stringa obbligatoria destinata all’utente. Passando $visible: false, il gruppo viene registrato nello stato OFF della configurazione predefinita, così il reader lo nasconde finché l’utente non lo attiva.

La visibilità dipende dalla cooperazione del reader. Il criterio di visibilità predefinito per un dizionario di appartenenza è AnyOn: il livello è visibile se almeno uno dei gruppi referenziati è ON. Un livello nascosto lo è solo per convenzione del reader. Non viene rimosso né protetto e non costituisce né oscuramento né controllo di sicurezza. Per rimuovere contenuto, non disegnarlo.

La superficie dell’API è generata automaticamente da PHPDoc. Questa ricetta utilizza due metodi:

  • startLayer(string $name, bool $visible = true): static — apre un OCG denominato; $visible: false lo nasconde per impostazione predefinita.
  • endLayer(): static — chiude il livello aperto più di recente (bilanciato con 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');

Questo è l’esempio completo, pronto per il harness. Rispetta NEXTPDF_COOKBOOK_OUTPUT e non introduce alcuna entropia propria.

<?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";
  • Bilanciare ogni startLayer() con un endLayer(). Un livello non chiuso lascia un BDC pendente senza il relativo EMC, rendendo malformata la struttura del documento. Abbinare ogni chiamata di apertura alla relativa chiamata di chiusura.
  • Un livello nascosto non viene rimosso. visible: false nasconde il contenuto solo per convenzione del reader. I marcatori e l’eventuale testo restano nel file e sono recuperabili. Questo non è un oscuramento. Per i dati sensibili, non disegnarli.
  • Il supporto del pannello dei livelli varia. L’attivazione e la disattivazione richiedono un reader che esponga il contenuto opzionale. Le pipeline di stampa e i visualizzatori minimali possono mostrare sempre, oppure nascondere sempre, i livelli disattivati per impostazione predefinita.
  • Annidamento. I livelli annidati sono consentiti, ma la visibilità di ogni gruppo interno resta comunque indipendente. Non dare per scontato che un livello esterno OFF nasconda un gruppo interno ON, se non viene collegato un criterio di appartenenza.

Ogni livello aggiunge un dizionario OCG e una coppia BDC/EMC attorno ai relativi marcatori. L’overhead risultante è trascurabile. Il costo cresce in proporzione al contenuto all’interno dei livelli, non al numero di livelli; quindi questa ricetta rimane ampiamente entro il budget di 2000 ms / 64 MB.

La visibilità del contenuto opzionale dipende dalla cooperazione del reader; non è un controllo degli accessi. Nascondere un livello non cifra, non oscura e non rimuove il contenuto. Chiunque può riattivare il livello o estrarne i byte. Non utilizzare mai un livello nascosto per occultare testo riservato; omettere invece del tutto il contenuto. Questa ricetta non esegue alcun parsing dell’input né accessi alla rete.

EnunciatoStandardClausolareference_id
Un dizionario OCG ha Type /OCG.ISO 32000-2§8.11.2
Il Name dell’OCG è l’etichetta obbligatoria destinata all’utente.ISO 32000-2§8.11.2
Il contenuto opzionale è racchiuso tra BDC/EMC con il tag OC.ISO 32000-2§8.11.3.2
I criteri OCMD sono AllOn/AnyOn/AnyOff/AllOff (predefinito AnyOn).ISO 32000-2§8.11.4.3

Profilo di riproducibilità — strutturale. Il /ID del trailer e gli atomi della data variano a ogni salvataggio. L’harness rimuove tali atomi e confronta la struttura normalizzata con qpdf. Questa ricetta descrive come NextPDF produce tale struttura. Non dichiara una conformità generale a ISO 32000-2.

Non applicabile. I gruppi di contenuto opzionale sono una funzionalità di Core, senza limitazioni Premium.