Premessa
Lo scopo del presente articolo è di affrontare le problemiche connesse alla generazione di documenti in formo PDF con MS Visual Basic, senza l'ausilio di nessun controllo OCX, libreria DLL o software di terze parti.
Nella prima parte procederemo ad una breve analisi di un documento PDF, evidenziandone la struttura e gli elementi costitutivi. Affronteremo quindi le problemiche relive alla gestione dei font, della grafica vettoriale e delle immagini raster.
Nella seconda parte vedremo come queste conoscenze possono essere utilizze per sviluppare una serie di funzione, in particolare sarà presenta una classe di esempio, di libero utilizzo ed implementazione.
Per brevità, non affronteremo il problema della compressione dei di, della revisione o modifica di un file creo in precedenza, né vedremo come realizzare le miniure o la struttura ad indice del documento. Inoltre nell'articolo non saranno affronti alcuni dettagli dell'implementazione, lasciando al pubblico "avanzo" la possibilità di autoreferenziare l'esempio proposto.
Gli elementi di base
Un file PDF è sostanzialmente un file di testo, inteso come sequenza di carteri e separori di linea (Chr(13)), di tipo strutturo, ovvero in cui le informazioni assumono un particolare significo in quanto inserite in strutture che rispettano una particolare sintassi.
Gli elementi di base sono gli oggetti "obj", che all'occorrenza possono contenere sequenze "stream", dizionari "dictonary" o altro. Un oggetto può rappresentare una pagina, un'immagine, una sequenza grafica, ecc.
Ogni oggetto, racchiuso tra le parole chiavi obj e endobj è identifico da un numero e da una revisione. Visto che non prenderemo in considerazione le modifiche di file crei in precedenza, tutti i nostri oggetti avranno come numero di revisione 0 (zero).
2 0 obj
.. .. .. .. ..
endobj
Gli oggetti non devono necessariamente presentarsi in ordine numerico ed è possibile fare riferimento ad un oggetto "futuro", ovvero non ancora definito; ciò risulta particolarmente utile e forse indispensabile in alcuni casi (ad esempio quando nel file è necessario indicare la lunghezza di un testo prima che il testo stesso sia sto inserito). Quando è necessario effettuare un riferimento ad un oggetto, basta indicare il suo numero e la revisione seguiti dalla lettera "R".
.. ..
/Parent 3 0 R
.. ..
In generale ogni qualvolta è necessario utilizzare più volte lo stesso oggetto in più punti del documento, sia esso una immagine, sia esso una generica risorsa, ai fini dell'occupazione di memoria e della velocità di visualizzazione, conviene creare un oggetto che contenga la risorsa e utilizzare un riferimento a questo ogni qualvolta si rende necessario.
Le sequenze di di sono racchiusi tra le parole chiavi stream e endstream. Possono contenere qualsiasi sequenza di carteri (anche quelli non stampabili) e servono a descrivere un testo, un'immagine o altro.
stream
.. sequenza di carteri ..
endstream
I dizionari sono coppie variabile/valore racchiuse tra i delimitori << e >>. Vengono utilizzi per carterizzare particolari oggetti, definendone gli tributi. Un valore può essere espresso con una costante numerica (la parte decimale prevede il punto e non la virgola), una stringa alfanumerica (delimita da una coppia di parentesi tonde), con un ulteriore dizionario, con un riferimento ad un oggetto o con un array (delimito da una coppia dei parentesi quadre).
<<
/Type /Page
/Parent 3 0 R
/Resources << /ProcSet 6 0 R >>
/MediaBox [0 0 612 792]
.. .. ..
>>
Un file PDF non è altro che una opportuna sequenza di oggetti, costruiti rispettando una sintassi abbastanza semplice (tenzione alle maiuscole e minuscole), legi fra loro da riferimenti specifici, corredo da quanto necessario all'applicivo che legge il file (ad esempio Acrob Reader) per sapere dove recuperare le informazioni ed in quale ordine.
Struttura fisica di un file PDF
La struttura fisica di file PDF può essere riassunta nel seguente schema.
| HEADER |
BODY
|
| CROSS-REFERENCE TABLE |
| TRAILER |
La sezione HEADER contiene informazioni utili al software Reader per identificare il tipo di file e lo standard PDF utilizzo. E' rappresenta dalla prima riga del file ed è del tipo
%PDF-1.3
ove il simbolo % indica in genere una riga di commento e 1.3 indica che per leggere correttamente le informazioni contenute nel file è necessario Acrob Reader 4.0 (piuttosto che 1.4 per il quale è necessario Acrob Reader 5.0, piuttosto che 1.5 per Acrob Reader 6.0). Nel prosieguo, noi considereremo di operare sempre con formi compibili con Acrob Reader 4.0 ovvero con una specifica %PDF-1.3.
La sezione BODY contiene gli oggetti che saranno rappresenti sulle pagine e sui quali ci soffermeremo in seguito.
La sezione CROSS-REFERENCE TABLE è una tabella che riporta un riferimento ad ogni oggetto presente nella sezione BODY e alla sua eventuale revisione; in particolare indica la posizione del primo cartere della definizione di un oggetto rispetto all'inizio del file e il numero di revisione a cui si riferisce.
xref
0 23
0000000019 65535 f
0000000009 00000 n
.. .. ..
0000000300 00000 n
0000000384 00000 n
La sezione TRAILER indica al Reader quanti oggetti sono presenti nella sezione BODY (/Size), qual è l'oggetto iniziale (/Root), quale oggetto contiene le informazioni generali del documento quali autore, titolo, da di creazione (/Info), dove trovare la CROSS-REFERENCE TABLE ed inoltre segna la fine del file (%%EOF).
trailer
<<
/Size 7
/Root 1 0 R
/Info 2 0 R
>>
startxref
408
%%EOF
Struttura logica di un documento PDF
La struttura logica di un documento PDF può essere riassunta nel seguente schema.
L'oggetto CALOG rappresenta la radice dell'intero documento e deve essere quello a cui punta il riferimento /Root presente nella sezione TRAILER.
1 0 obj
<<
/Type /Calog
/Pages 3 0 R
/Outlines 20 0 R
>>
endobj
A sua volta, contiene un riferimento alla radice delle pagine (/Pages) e un riferimento alla radice della struttura ad albero che fa da indice (/Outlines), quello che di solito quando si apre un documento con Acrob Reader, appare a sinistra della pagina e permette di muoversi velocemente nel documento, e che noi per semplicità non analizzeremo.
L'oggetto PAGES rappresenta la radice delle pagine, indica il numero complessivo delle pagine del documento (/Count) e riporta un riferimento all'oggetto che contiene ogni pagina (/Kids).
3 0 obj
<<
/Type /Pages
/Count 3
/Kids [4 0 R 8 0 R 10 0 R]
>>
endobj
L'oggetto PAGE riporta un riferimento alla propria radice (/Parent), un elenco delle risorse utilizze nella pagina (/Resources) (vedremo in seguito cosa sono), un array con le dimensione del formo di stampa previsto (/MediaBox) ed infine un riferimento all'oggetto che contiene gli elementi da rappresentare sulla pagina (/Contents).
4 0 obj
<<
/Type /Page
/Parent 3 0 R
/Resources
<<
/ProcSet [/PDF /Text]
>>
/MediaBox [0 0 595.2 842]
/Contents 5 0 R
>>
endobj
Se nel documento si vogliono riportare informazioni relive all'autore, all'applicivo che ha genero il file o la da di creazione, si può utilizzare il seguente oggetto (tenzione alle parentesi che fanno parte della sintassi). Queste informazioni appaiono se dal Reader si visualizzano le proprietà del documento.
2 0 obj
<<
/Title (titolo_del_documento)"
/Author (autore_del_documento)"
/Creor (applicivo_generore)"
/Producer (info_copyright)"
/CreionDe (D:yyyymmddhhmmss+01'00')
>>
Il sistema di coordine
Il sistema di coordine predefinite in documento PDF ha come unità di misura il punto, definito come 1/72 di pollice. L'origine degli assi è posta nell'angolo in basso a sinistra. In questo sistema, il normale foglio A4 (21x29.7 cm) ha dimensione 595.2x842 punti. Per default tutte le immagini, a meno di una esplicita traslazione/scalura/rotazione, hanno dimensione 1x1 e sono poste con lo spigolo inferiore sinistro nell'origine (0,0).
Gli operori
Per la definizione degli elementi contenuti in ogni pagina, la sintassi dello standard PDF prevede l'uso di alcuni operori. Di seguito vedremo quelli necessari ai fini di questo articolo, rimandando ai testi in bibliografia per una descrizione più dettaglia. In particolare, bisogna tener conto che gli operori grafici descrivono solo un percorso (ph) che verrà traccio fisicamente solo quando verrà utilizzo un apposito operore e che le componenti di colore vanno da 0 a 1 e non da 0 a 255.
|
OPERORE
|
DESCRIZIONE
|
|
X Y m
|
Muove il punto di inserimento grafico alle coordine (X,Y)
|
|
X Y l
|
Aggiunge una linea dal punto corrente al punto (X,Y) alla ph
|
|
X w
|
Imposta la larghezza della linea a X punti
|
|
h
|
Chiude una ph, disegnandone il traccio
|
|
n
|
Termina un ph
|
|
f
|
Chiude una ph e colora la regione delimita
|
|
r g b RG
|
Imposta il colore per i contorni
|
|
r g b rg
|
Imposta il colore per le aree
|
|
gray G
|
Imposta un tono di grigio per i contorni
|
|
gray g
|
Imposta un tono di grigio per le aree
|
|
x1 y1 x2 y2 x3 y3 c
|
Aggiunge una curva Bezier alla ph
|
|
x y width height re
|
Aggiunge un rettangolo alla ph
|
|
W 0 0 H X Y cm
|
Mrice di trasformazione grafica di coordine
|
|
S
|
Traccia la ph
|
|
s
|
Chiude e traccia la ph
|
|
B
|
Traccia la ph e colora la regione
|
|
BT
|
Inizia una sequenza di testo
|
|
ET
|
Termina una sequenza di testo
|
|
space Tc
|
Imposta la spaziura tra carteri in millesimi di punto
|
|
space Tw
|
Imposta la spaziura tra parole in millesimi di punto
|
|
scale Tz
|
Imposta la scalura percentuale dei carteri
|
|
space TL
|
Imposta l'interlinea
|
|
X Y Td
|
Imposta il punto di inserimento del testo
|
|
fontname size Tf
|
Imposta il font e la dimensione del cartere
|
|
string Tj
|
Visualizza la stringa con il font corrente
|
|
/name Do
|
Esegue l'oggetto name
|
Gli elementi di uso comune - Font e testo
Uno dei primi oggetti che analizziamo è l'oggetto necessario a descrivere un font. In questa fase vedremo come utilizzare uno dei 14 fonti TYPE1 predefiniti nel linguaggio PDF, ovvero font che il Reader conosce già e che non necessitano di particolari informazioni (viceversa, per altri tipi di font TrueType occorre fornire informazioni dettaglie, come ad esempio la larghezza in punti di ogni singolo cartere).
I 14 font predefiniti TYPE1 sono :
CourierNew (.Italic, .Bold, .BoldItalic)
Arial (.Italic, .Bold, .BoldItalic)
TimesNewRoman (.Italic, .Bold, .BoldItalic)
ZapfDingbs
Symbol
Per poterne utilizzare uno, occorre creare un oggetto che lo contenga. Nell'esempio che segue, l'oggetto 7, contiene il font Arial con tributi Grassetto e Corsivo, al font viene do il nome Fn1 e come tabella carteri viene indica quella ANSI.
7 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /Fn1
/BaseFont /Arial.BoldItalic
/Encoding /WinAnsiEncoding
>>
endobj
Quindi volendo scrivere il classico "Hello World" alla posizione di coordine (100,400) con il font definito in precedenza di nome Fn1, basterà inserire in un oggetto la sequenza
% Scrive Hello World in Arial Bold Italic 24 punti
BT
/Fn1 24 Tf
100 400 Td
(Hello World) Tj
ET
Gli elementi di uso comune - Grafica vettoriale
Se vogliamo inserire degli elementi grafici, basterà inserire una sequenza del tipo
% Traccia un rettangolo rosso pieno con contorno blue
.5 .75 1 rg
1 0 0 RG
200 300 50 75 re
B
% Traccia una linea con spessone 2 punti
2 w
150 250 m
150 350 l
S
Gli elementi di uso comune - Immagini raster
Un altro oggetto di uso comune è quello necessario per rappresentare delle immagini di tipo raster (BMP). Per le immagini è possibile optare per due modalità: creare un oggetto che può essere richiamo ogni volta che la stessa immagine deve essere visualizza, anche se con dimensioni diverse (ed è questo il caso che noi analizzeremo) o definire l'immagine all'interno della pagina senza la possibilità di poterla riutilizzare.
Ad esempio se si definisce una immagine Img1, 10 pixel per 5, 24 bit colore (8 x 3 componenti colore RGB), utilizzando una rappresentazione esadecimale, sono necessari 150 campioni, ovvero 10 x 5 x 3.
12 0 obj
<<
/Type /XObject
/Subtype /Image
/Name /Img1
/Width 10
/Height 5
/BitsPerComponent 8
/ColorSpace /DeviceRGB
/Filter /ASCIIHexDecode"
/Length 13 0 R
>>
stream
80 A1 2F .. .. %150 campioni esadecimali
endstream
endobj
13 0 obj
150
endobj
Notare come al posto della lunghezza dello stream è sto utilizzo un riferimento ad un oggetto (13 0) che contiene (solo) il valore 150.
Se vogliamo visualizzare l'immagine con l'angolo inferiore sinistro nel punto (100, 80), con una dimensione orizzontale 200 e una verticale di 300, sarà sufficiente inserire la sequenza
q % salva lo sto grafico corrente
200 0 0 300 100 80 cm % mrice di trasformazione di coordine
% necessaria per spostare/ingrandire l'immagine
/Img1 Do % visualizza l'immagine Img1
Q % ripristina lo sto grafico precedente
Analogamente la sequenza
.. ..
/BitsPerComponent 8
/ColorSpace /DeviceGray
/Length 50
>>
stream
$-#etT .. .. %50 carteri
endstream
endobj
individua un'immagine in toni di grigio (1 sola componente colore), rappresenta con una sequenza di 50 campioni (10x5x1)
Gli elementi di uso comune - Le Form
Capita spesso che porzioni di documenti, vadano riprodotte più volte, come ad esempio le intestazioni, i piè di pagina, i wermark (quelle scritte oblique sotto al testo tipo bozza, uso interno, …). Lo standard PDF prevede l'uso di un particolare oggetto, appunto le form, che chiariamo subito, non hanno nulla a che fare con le form di Visual Basic. Ad esempio tutto ciò che è contenuto nello stream dell'oggetto 13 con nome Frm1 (il significo degli altri tributi lo vedremo la prossima volta),
13 0 obj
<<
/Type /XObject
/Subtype /Form
/FormType 1
/Name /Frm1
/BBox [0 0 595.2 842]
/Mrix [1 0 0 1 0 0]
/Length 14 0 R >>
stream
.. .. .. .. ..
endstream
endobj
può essere riprodotto, ovunque, con la sequenza
/Frm1 Do
Conclusioni
Quanto descritto è un buon punto di partenza per la realizzazione di una propria libreria per creazione di documenti PDF, indipendentemente dal linguaggio utilizzo.
Nella seconda parte vedremo come applicare e sfruttare il tutto in Visual Basic 6.0, commentando e realizzando un esempio completo.
Per chi non riesce a resistere fino alla prossima punta, consiglio di iniziare a smanettare con un documento PDF (piccolo, magari da 1 sola pagina), aprendolo con un elaborore di testi (ad esempio WordPad) e provare a riconoscere le strutture descritte.
Bibliografia
Per maggiori informazioni e approfondimenti sugli argomenti trti in questo articolo, consiglio le seguenti letture:
"PDF Reference 15"
http://partners.adobe.com/asn/tech/pdf/specificions.jsp
"Documentazione ed editoria elettronica mediante tecnologia PDF" - Tesi di laurea
http://elite.polito.it/tesi/bertoghisio.pdf