PDF/E-1 è il profilo di archiviazione per i documenti tecnici, e PDFlibPas lo implementa come una modalità author da attivare con SetPDFEMode più un preflight limitato che legge i content stream operatore per operatore. Il profilo non è un PDF/A con etichetta diversa: ha un namespace di identificazione proprio, un requisito di metadati del ciclo di vita proprio, e una regola che rende la validazione del contenuto più severa di qualsiasi profilo di archiviazione tu abbia mai incontrato
I deliverable dell'ingegneria sono il motivo per cui il profilo esiste. Un corredo di tavole che dovrà essere leggibile e dimostrabilmente invariato tra vent'anni, con uno storico revisioni che sopravvive, e con un colore che significa la stessa cosa sul plotter nell'altro edificio. Quei requisiti producono una specifica le cui richieste stanno per lo più fuori dal contenuto di pagina, nei metadati e nella gestione del colore, che è esattamente dove un generico writer PDF le sbaglia
Un'identificazione propria, non una variante del PDF/A
La prima cosa da azzeccare è che l'identificazione PDF/E-1 non si produce adattando lo schema di PDF/A o PDF/X. Usa un namespace XMP distinto, http://www.aim.org/pdfe/ns/id/, e il valore di versione deve comparire in due posti: come voce nelle informazioni del documento e come proprietà XMP qualificata dal namespace. Emettere solo la proprietà XMP, o solo la voce nelle informazioni, produce un file che porta l'intenzione e fallisce la validazione
L'output intent ha una forma altrettanto specifica. PDF/E-1 richiede un profilo ICC incorporato con l'identificativo di sottotipo ISO_PDFE1, e il profilo deve avere un numero di componenti corrispondente alla famiglia di colori device che il documento usa davvero. È nell'ultima clausola che le implementazioni sbagliano in silenzio, perché significa che l'output intent non può essere scelto all'inizio e poi ignorato
Perché il colore device richiede una scansione dell'intero documento?
Perché i color space si nascondono nei dizionari risorse che una scansione a livello di pagina non raggiunge mai. PDF/E-1 tratta DeviceRGB e DeviceCMYK come famiglie mutuamente esclusive per un documento, quindi validare il profilo significa conoscere ogni color space device usato da qualsiasi cosa nel file. Un form XObject ha le proprie risorse. Anche un pattern, e anche un'immagine. Un tiling pattern dentro un form XObject dentro una pagina è a tre livelli di profondità, e un validatore che controlla solo le risorse di primo livello della pagina farà passare un documento che usa entrambe le famiglie
La scansione quindi registra i color space mentre percorre pagine, form, immagini e pattern come un'unica traversata, e solo dopo decide se il documento è coerente e se l'output intent corrisponde. Lo stesso ragionamento guida in generale l'architettura del preflight: una traversata parziale produce falsi passaggi, e un falso passaggio su un controllo di conformità è peggio di nessun controllo, perché viene registrato come prova
var
Lib: TPDFlib;
Diag: WideString;
begin
Lib := TPDFlib.Create(nil);
try
Lib.LoadFromFile('assembly-drawings.pdf');
if Lib.SetPDFEMode(1) = 0 then
raise Exception.Create('PDF/E author mode was refused');
// La modalità author tiene allineati i metadati del ciclo di vita a ogni salvataggio.
// Chiedi prima di salvare se il documento passerebbe la propria barriera
if not Lib.PDFEReadyForSave then
begin
Diag := Lib.GetPDFEDiagnostics;
Writeln('PDF/E blockers: ', Diag);
Exit;
end;
Lib.SaveToFile('assembly-drawings-pdfe.pdf');
finally
Lib.Free;
end;
end;
I metadati del ciclo di vita sono un obbligo per ogni salvataggio
PDF/E-1 chiede più di un identificativo di documento. L'insieme minimo comprende l'identificativo documento di media management, un identificativo di versione, una rendition class, il tempo di creazione, il tempo di modifica, il tempo dei metadati e un titolo. È un vocabolario per il tracciamento delle revisioni, ed esiste perché da un deliverable di ingegneria ci si aspettano riemissioni, non una stesura unica
La conseguenza per un'implementazione è che questi campi non si possono impostare alla creazione del documento. Se il tempo di modifica viene scritto quando attivi la modalità e il documento viene poi modificato, lo snapshot XMP e lo stato effettivo del documento divergono, e un validatore che li confronta riporta un'incongruenza che nessuno voleva. La modalità author quindi sincronizza i campi immediatamente prima di ogni salvataggio, così i metadati descrivono i byte che stanno per essere scritti invece dei byte che esistevano quando la modalità è stata attivata
È un principio generale per i metadati di conformità e vale la pena enunciarlo separatamente dal PDF/E: i metadati derivati appartengono al percorso di salvataggio, non a quello di modifica. Qualsiasi campo calcolato dallo stato del documento va ricalcolato nel momento in cui lo stato viene congelato, altrimenti è una cache senza invalidazione
La regola che rende severa la validazione del contenuto
PDF/E-1 non permette agli operatori di sezione di compatibilità di assorbire contenuto sconosciuto. Nel PDF ordinario, BX e EX delimitano una regione in cui un consumer deve ignorare gli operatori che non riconosce, ed è la via di fuga che permette a un producer di emettere costrutti più recenti senza rompere i reader più vecchi. Sotto PDF/E-1 quella via di fuga è chiusa, quindi qualsiasi operatore che il preflight non riconosce viene riportato incondizionatamente, che stia dentro una sezione di compatibilità o no
L'effetto su un validatore è notevole. Non può saltare le regioni che non capisce, il che significa che il parser degli operandi deve davvero analizzare ogni operatore in ogni content stream. Ed è qui che entrano i limiti. La traversata è limitata a 128 livelli di annidamento, un milione di oggetti e 64 MiB di contenuto, e quei limiti non sono taratura delle prestazioni. Un file ostile o semplicemente corrotto può presentare un grafo di oggetti con cicli o una profondità di annidamento che trasforma un validatore ricorsivo in uno stack overflow, e sono i limiti a impedire che un passaggio di validazione diventi un vettore denial-of-service. La stessa postura difensiva è descritta in parsing sicuro di PDF non fidati
// Validazione standalone di un file che non hai prodotto, senza caricarlo
// in un'istanza di documento
var
Issues: TStringList;
Stream: TFileStream;
I: Integer;
begin
Issues := TStringList.Create;
Stream := TFileStream.Create('incoming.pdf', fmOpenRead or fmShareDenyWrite);
try
if CheckCompliancePDFE(Stream, '', 0, Issues) = 0 then
for I := 0 to Issues.Count - 1 do
Writeln('PDF/E: ', Issues[I]);
finally
Stream.Free;
Issues.Free;
end;
end;
Cosa ripara la barriera di salvataggio e cosa rifiuta
La barriera divide il lavoro in due stadi, e la divisione è di per sé un'idea di design riutilizzabile. Prima normalizza ciò che è riparabile in sicurezza: i flag di stampa delle annotazioni, i flag no-zoom e no-rotate delle annotazioni di testo, e il flag di generazione dell'aspetto sul dizionario del form. Sono impostazioni con un solo valore corretto sotto il profilo e nessun contenuto informativo, quindi correggerle in silenzio è giusto e rifiutare per esse sarebbe pedanteria
Poi controlla i vincoli che non si possono riparare senza cambiare ciò che il documento significa: versione, identificazione, cifratura, output intent, coerenza del colore device e presenza di contenuto di form dinamico. Un documento che ne fallisce anche uno solo viene rifiutato, perché inventare un output intent o scegliere una famiglia di colori per conto dell'autore produrrebbe un file che passa la validazione e falsa il contenuto
Rileggere la diagnostica tramite GetPDFEDiagnostics prima di salvare trasforma quel rifiuto in una lista su cui agire invece che in un'operazione fallita. In una pipeline batch, chiamala su ogni documento, logga i bloccanti per file, e instrada i fallimenti verso una fila che una persona guarda. È molto più utile di un salvataggio che solleva eccezioni, perché i bloccanti di solito si aggregano: quaranta documenti che falliscono per lo stesso output intent mancante sono una correzione, non quaranta
Scegliere tra i profili di archiviazione
PDF/E-1 è il bersaglio giusto quando il deliverable è documentazione di ingegneria con un ciclo di vita a revisioni, e in particolare quando la coerenza del colore device conta perché l'output va a plotter e stampanti large-format. PDF/A è il bersaglio giusto quando l'obiettivo è la leggibilità a lungo termine dei documenti in generale, ed è il profilo con il supporto di validazione più ampio. I due non sono intercambiabili, e un documento può soddisfare l'uno e fallire l'altro
Se stai scegliendo, parti da chi valida il file all'estremo ricevente. Gli strumenti di validazione PDF/A sono ovunque, e il corrispondente preflight in PDFlibPas è descritto in preflight PDF/A e PDF/UA. La validazione PDF/E è più specializzata e di solito è un requisito contrattuale, non un default. Quando un archivio esistente va portato a un profilo per cui non è mai stato scritto, il percorso di riparazione metadati in conversione a PDF/A con riparazione dei metadati è lo schema da seguire, e qui vale la stessa forma: identifica, ripara ciò che è sicuro, rifiuta il resto con una lista
La modalità author, il preflight limitato del contenuto e la verifica di conformità standalone sono tutti inclusi nella PDFlibPas Delphi PDF library, così un documento può essere prodotto sotto il profilo e verificato in seguito in modo indipendente attraverso un percorso di codice separato, che è l'unica disposizione a cui valga la pena fidarsi per una dichiarazione di conformità