Il PDF non è un formato di documento come lo sono Word o RTF. Quei formati memorizzano una sequenza di contenuti che un motore di rendering interpreta al momento della visualizzazione, quindi l'output dipende da eventuali font e motori di layout presenti. Il PDF memorizza il risultato di quel processo: istruzioni di rendering precise, programmi per i font, flussi di immagini compressi e un grafo di oggetti che li collega in una descrizione autonoma di ogni pagina. Il file contiene informazioni sufficienti per riprodurre ogni pagina in modo identico su qualsiasi motore di rendering conforme, che è sia il suo obiettivo di progettazione principale sia la fonte della maggior parte della complessità che si incontra quando si cerca di generarne, analizzarne o modificarne uno a livello di programmazione
Il modello a oggetti
Ogni PDF è una raccolta di oggetti numerati. Un oggetto può essere un booleano, un intero, un numero reale, un nome, una stringa, un array, un dizionario, un flusso (stream) o null. Quasi tutto ciò che è interessante è un dizionario, ovvero un insieme di coppie chiave-valore in cui le chiavi sono nomi e i valori sono qualsiasi altro tipo di oggetto, inclusi riferimenti ad altri oggetti per numero e conteggio di generazione. Un flusso è un dizionario seguito da una sequenza di byte, tipicamente compressa
Il dizionario del catalogo (catalog) è la radice. Esso punta all'albero delle pagine (page tree), che organizza i dizionari delle pagine in una struttura ad albero bilanciata anziché in un elenco piatto, per cui la navigazione alla pagina 5.000 di un documento di 10.000 pagine non richiede l'attraversamento di ogni descrittore di pagina precedente. Ogni dizionario di pagina fa riferimento ai suoi flussi di contenuto (una o più sequenze di operatori di descrizione della pagina), al suo dizionario delle risorse (che a sua volta fa riferimento a descrittori di font, spazi colore e XObject immagine) e al suo media box (lo spazio delle coordinate in cui risiede la pagina). L'origine delle coordinate è nell'angolo in basso a sinistra, con le Y positive dirette verso l'alto, in unità di 1/72 di pollice
Alla fine del file si trova la tabella dei riferimenti incrociati (cross-reference table), che mappa ogni numero di oggetto al suo offset in byte nel file. Questo è ciò che consente l'accesso casuale: un visualizzatore legge prima la tabella dei riferimenti incrociati, quindi cerca direttamente gli oggetti di cui ha bisogno. Il PDF 1.5 ha introdotto i flussi di riferimenti incrociati, che comprimono la tabella in un oggetto stream e impacchettano gli oggetti correlati in object stream, riducendo notevolmente le dimensioni del file per i documenti con molti oggetti piccoli
Flussi di contenuto e modello grafico
Il contenuto visivo di una pagina risiede in uno o più flussi di contenuto. Ogni flusso è una sequenza di operatori PDF intervallati dai loro operandi. L'operatore di testo BT inizia un oggetto di testo, Tf seleziona un font e una dimensione dal dizionario delle risorse, Td posiziona il cursore di testo, Tj o TJ disegna una stringa e ET chiude l'oggetto di testo. La grafica vettoriale segue uno schema simile: m imposta un punto di partenza per un tracciato, l aggiunge un segmento di linea, c aggiunge una curva di Bezier e f o S riempie (fill) o traccia (stroke) il percorso
Lo stato grafico (graphics state) governa tutto ciò che accade tra gli operatori: matrice di trasformazione corrente, larghezza della linea, spazio colore, colore di riempimento, colore del tratto e percorso di ritaglio (clipping path). Operatori come q e Q inseriscono e rimuovono lo stato grafico su uno stack, che è il modo in cui il PDF implementa trasformazioni di coordinate locali e sovrascritture temporanee dello stato senza influenzare il contesto circostante. I Form XObject generalizzano questo concetto: un flusso di contenuto autonomo con il proprio dizionario delle risorse che può essere disegnato su una pagina in posizioni arbitrarie e scalato con un singolo operatore Do
Incorporamento dei font ed estrazione del testo
Il PDF può fare riferimento ai font per nome e fare affidamento sul visualizzatore per sostituire qualcosa, ma in pratica qualsiasi documento che si intende condividere deve incorporare i dati del font. Un font Type 1 o TrueType/OpenType incorporato in un PDF porta un dizionario descrittore del font che punta a un flusso di file del font. Per i font TrueType, quel flusso contiene il programma binario del font; per i Type 1, sono i dati PFB. Il subsetting, che è ciò che fa ogni serio generatore di PDF, rimuove i glifi non referenziati dal documento, mantenendo le dimensioni del file gestibili anche per grandi font Unicode
L'estrazione del testo è il punto in cui l'incorporamento dei font presenta delle insidie. La rappresentazione visiva di un carattere è determinata da un glifo nel programma del font incorporato. Il valore Unicode di quel carattere è determinato da un flusso ToUnicode CMap allegato al dizionario del font. Quando la ToUnicode CMap è mancante o errata, un visualizzatore PDF può rendere il testo in modo leggibile ma non può estrarlo come Unicode significativo, motivo per cui il copia-incolla da alcuni PDF produce caratteri incomprensibili. Il Tagged PDF (ISO 32000 §14.8) aggiunge un secondo livello: un albero di struttura logica che mappa il contenuto della pagina su ruoli semantici del documento come paragrafi, intestazioni e celle di tabella. Gli screen reader e i motori di reflow utilizzano l'albero della struttura piuttosto che l'ordine grezzo del flusso di contenuto, il che spiega perché un PDF visivamente ben impaginato possa ancora essere inaccessibile se la codifica (tagging) è assente o errata
Aggiornamenti incrementali e firme digitali
Quando si salvano le modifiche a un PDF esistente senza riscriverlo da zero, i nuovi oggetti vengono aggiunti dopo il corpo originale del file, insieme a una nuova sezione di riferimenti incrociati e a un nuovo dizionario trailer. Il trailer aggiornato punta ai nuovi dati di riferimento incrociato e gli oggetti sostituiti rimangono nel file ma semplicemente non sono più referenziati dalla nuova catena di riferimenti incrociati. Questo è l'aggiornamento incrementale (incremental update), e ha due conseguenze significative
In primo luogo, il file cresce a ogni ciclo di salvataggio. Un documento modificato e salvato ripetutamente accumula strati di oggetti obsoleti. Strumenti come QPDF possono linearizzare o comprimere e riscrivere un file per recuperare quello spazio, ma l'impostazione predefinita è l'accumulo. In secondo luogo, le firme digitali dipendono dagli aggiornamenti incrementali per il loro modello di integrità. Una firma ISO 32000 copre un intervallo di byte (byte range) del file, tipicamente tutto tranne il segnaposto per il valore della firma stessa. Eventuali modifiche successive alla firma che appaiono come aggiornamenti incrementali aggiuntivi sono visibili a un lettore incaricato della convalida come modifiche apportate dopo la firma, che è esattamente il registro di controllo che si desidera. Tuttavia, questo significa anche che alcune modifiche, come l'aggiunta di una firma di approvazione o la compilazione di campi modulo, sono esplicitamente consentite dallo standard senza invalidare la firma originale, a condizione che le modifiche siano conformi alle impostazioni di autorizzazione del documento (ISO 32000-2 §12.7.6). Una modifica che non rientra in tali permessi viene contrassegnata come non autorizzata. Comprendere questa distinzione è importante quando si generano documenti che verranno controfirmati a valle
Livelli di conformità e la discendenza di ISO 32000
Il PDF è nato come formato Adobe proprietario nel 1993, ha assorbito il modello di imaging di PostScript e in quindici versioni ha accumulato funzionalità: crittografia nella 1.1, moduli interattivi nella 1.2, firme digitali e struttura logica nella 1.3, trasparenza nella 1.4, object stream nella 1.5, crittografia AES nella 1.6. Adobe ha presentato il PDF 1.7 all'ISO nel 2007 e il risultato è stato ISO 32000-1:2008. ISO 32000-2:2020 copre il PDF 2.0, che ha reso più rigorose diverse aree poco specificate, ha rivisto la derivazione della chiave AES-256 (revisione 6 in sostituzione della revisione 5) e ha aggiunto il supporto esplicito per file associati e rich media
I sotto-standard derivano dalla stessa base. PDF/A (ISO 19005) baratta le funzionalità per la stabilità dell'archiviazione: nessuna crittografia, nessuna dipendenza da contenuti esterni, tutti i font incorporati, spazi colore indipendenti dal dispositivo, metadati XMP obbligatori. PDF/A-1 è basato su PDF 1.4, PDF/A-2 su PDF 1.7, PDF/A-3 consente file incorporati di qualsiasi formato. PDF/X (ISO 15930) è il sottoinsieme per la produzione di stampa: intenti di output, box di abbondanza e di ritaglio (bleed e trim boxes), nessuna trasparenza nei livelli di conformità precedenti. PDF/UA (ISO 14289) impone la struttura taggata, le mappature Unicode e i metadati della lingua per l'accessibilità. Questi non sono formati concorrenti; sono insiemi di vincoli aggiuntivi in cima al PDF di base e un singolo file può essere conforme a più di uno contemporaneamente, a condizione che i vincoli non siano in conflitto
Per chiunque scriva codice che genera o elabora PDF, la linea guida pratica è ISO 32000-2, con un'attenzione particolare alle sezioni che coprono il modello di riferimento incrociato (§7.5), lo stato grafico (§8.4), gli operatori di stato del testo (§9.3), i descrittori di font e ToUnicode (§9.6 e §9.10), i moduli interattivi (§12.7) e le firme digitali (§12.8). Lo standard è lungo, ma la maggior parte del lavoro programmatico sui PDF tocca ripetutamente una sua porzione ristretta. Comprendere il modello a oggetti e il meccanismo di riferimento incrociato è il punto di ingresso; tutto il resto è una specializzazione di questi