Documenti FirebirdAgli scrittori per FirebirdCome fare il manuale di Firebird → Avanzato: perfezionare i PDF
Firebird home Firebird home Indietro: Se qualcosa non vaPartenza: Documenti FirebirdRisali: Come fare il manuale di FirebirdAvanti: Revisioni

Argomento avanzato: perfezionare i PDF

Come viene ricostruito il PDF
Schema generale per la sistemazione
Problemi tipici e loro soluzioni
Riferimenti su XSL-FO

A causa delle limitazione nei sistemi di ricostruzione, il PDF generato può soffrire di alcuni irritanti difetti, quali:

Questa sezione vi mostra come affrontarli, nel caso vi sia la necessità.

Come viene ricostruito il PDF

La prima cosa da capire è come viene ricostruito il PDF. A differenza della generazione dell'HTML, è un processo in due passi:

  1. Il sorgente XML DocBook viene convertito in un file Formatting Objects (FO). Il formato FO – chiamato formalmente XSL-FO – è anch'esso un formato XML, ma a differenza del DocBook è orienato alla presentazione. Questo passo è effettuato da un cosiddetto XSL transformer chiamato Saxon. Il risultato va in manual/inter/filename.fo (per i documenti in italiano in manual/inter/it/filename.fo).

  2. Un secondo strumento, Apache FOP (Formatting Objects Processor), prende filename.fo e lo converte in filename.pdf, che è memorizzato in manual/dist/pdf (per i documenti in italiano in manual/dist/pdf/it).

Dando il comando build pdf, vengono ricostruiti internamente due consecutivi obiettivi: fo e fo2pdf, che corrispondono ai due passi descritti sopra. Però si possono chiamare distintamente dalla linea di comando. Ad esempio,

build fo -Drootid=qsg15

...trasforma il sorgente della Quick Start Guide 1.5 in manual/inter/qsq15.fo. E

build fo2pdf -Drootid=qsg15

...produce il PDF dal file FO (che deve ovviamente essere presente affinchè questo passo possa avere successo).

Pertanto, build pdf è solo un'abbreviazione per build fo seguito da build fo2pdf.

Questa impostazione permette di modificare il file FO manualmente prima di generare il PDF finale. E sarà esattamente quello che si farà per aggiustare alcuni di quei noiosi problemi che affliggono i nostri PDF.

Schema generale per la sistemazione

In generale, la procedura per migliorare il PDF in uscita modificando il file FO è:

  1. Costruire il PDF una prima (ed unica) volta volta come al solito con build pdf [argomenti]. Questo comando non dovrà più essere utilizzato.

  2. Cominciare a leggere il PDF e trovare il primo evidente problema.

  3. Aprire il file FO con un editor di testo o un editor XML.

  4. Riconoscere il punto nel file FO che corrisponde al problema nel PDF (vedremo come in dettaglio più avanti).

  5. Modificare il file FO per eliminare il problema (anche questo sarà dettagliato più oltre), e salvare le modifiche.

  6. Ricostruire il PDF, ma questa volta usando build fo2pdf [argomenti]. Non facendolo, si sovrascriverebbero le modifiche fatte al file FO, rigenerando lo stesso PDF dell'inizio e dovendo rifare tutte le modifiche daccapo.

  7. Controllare se il problema risulta effettivamente risolto e se si, cercare il successivo problema.

  8. Ripetere i punti dal 4 al 7 finchè non si è sistemato tutto il PDF.

Nota bene

  • Sebbene questo metodo di modificare il FO suggerisca che il problema sia nel file FO, in realtà non è vero. Il file FO è giusto, purtroppo Apache FOP non supporta tutte le specifiche carine definite dal formato XSL-FO (per il momento). Con le modifiche manuali, si costringe la generazione del PDF in un determinato modo.

  • È importante aggiustare le cose in ordine, dalla prima pagina all'ultima. Modificare il FO in un punto può comportare aggiustamenti verticali al corrispondente punto nel PDF: più linee, meno linee, linee che si spostano alla pagina successiva, ecc... Questi aggiustamenti possono influire su tutto ciò che segue.

    Per lo stesso motivo, si dovrebbe sempre passare al successivo problema solo dopo aver risolto il precedente. Ad esempio, non farsi una lista di tutte le testate di finestra (windowed headers) e poi iniziare a modificarle tutte insieme nel file FO. Aggiustando un widowed header sposta tutto il testo che segue in giù, e può creare altri windowed headers e toglierne altri.

  • In generale si potrebbe tenere aperto il file FO durante tutto il processo. Solo ricordarsi di salvare il file per rigenerare il PDF. Bisogna ricordarsi di chiudere comunque il file PDF prima di ogni rigenerazione: una volta che è aperto in Adobe (perfino nel Reader), gli altri processi non lo possono scrivere.

  • L'intero processo potrebbe diventare veramente lungo, così è meglio non aggiustare subito ogni piccola imperfezione, specialmente se si è alle prime armi nel maneggiare i file FO. In generale, solo le testate vedove sono veramente brutte, e rendono l'aspetto del documento veramente dilettantesco.

La prossima sezione tratta dei vari problemi e di come risolverli.

Problemi tipici e loro soluzioni

Testate vedove

Problema: Si tratta di testate o di titoli che restano isolati (il termine tecnico è vedovi) alla fine della pagina.

Causa: Apache FOP non supporta ancora l'attributo keep-with-next (mantieni con successivo), tranne che nelle righe di tabella.

Soluzione: Forzare un salto pagina all'inizio dell'elemento (tipicamente una sezione, ma potrebbe essere anche una lista, una tabella, o un'altro elemento) a cui il titolo o la testata appartengono.

Come: Se l'elemento ha un attributo id (si può vedere nel sorgente DocBook), si può allora cercare per quell'id nel file FO. Ad esempio, supponendo di aver appena generato la Firebird 2 Quick Start Guide e si sia riscontrato che il titolo Creating a database using isql sia posizionato alla fine di una pagina. Nel sorgente DocBook XML si può vedere che quello è il titolo di una sezione il cui id è qsg2-databases-creating. Cercando il testo qsg2-databases-creating dall'inizio del file FO, la prima cosa che si trova è probabilmente qualcosa di questo genere:

<fox:outline internal-destination="qsg2-databases-creating">

L'elemento fox:outline corrisponde al link nel pannello di navigazione alla sinistra del PDF. Così questa non è ancora la sezione vera e propria, e bisogna cercare oltre. Successivamente si trova:

<fo:block text-align-last="justify" end-indent="24pt"
          last-line-end-indent="-24pt"><fo:inline
   keep-with-next.within-line="always"><fo:basic-link
   internal-destination="qsg2-databases-creating">Creating a database...

In questo caso, l'id è il valore d'un attributo in un fo:basic-link. Pertanto ora siamo nell'indice iniziale o tabella dei contenuti (Table of Contents). Ancora non è il posto giusto.

Il terzo ed il quarto tentativo sono spesso un paio di linee dopo il secondo, per creare il numero di linea alla citazione nell'indice. Ma il quinto tentativo è di solito quello che si stà cercando (a meno che non ci siano altri link in avanti alla sezione in questione):

<fo:block id="qsg2-databases-creating">

Eccolo qua! La maggior parte degli elementi gerarchicamente di medio e basso livello in DocBook (preface, section, appendix, para ecc.) determinano un fo:block nel file FO. Adesso si deve modificare il file FO in modo da costringere Apache FOP a iniziare questa sezione a pagina nuova. Si modifica la linea in questo modo:

<fo:block id="qsg2-databases-creating" break-before="page">

Salvare la modifica e ricostruire il PDF, ricordandosi di usare build fo2pdf, e non build pdf. Il titolo della sezione adesso apparirà alla successiva pagina nuova, e si può passare al problema successivo.

E se l'elemento di DocBook non ha un suo id? Allora si dovrà cercare il (o parte del) titolo o della testata. Questo sarà un po' più complicato, perchè il titolo potrebbe contenere un a capo nel file FO, nel qual caso non verrebbe trovato. Oppure il titolo potrebbe contenere dei suoi elementi figli (ad esempio quote o emphasis). Questo impedirebbe di trovare il titolo completo. D'altra parte più si stringe il testo da cercare, più alta sarà la probabilità di trovare cose non correlate. In questo caso si dovrà adoperarre il proprio metro di gudizio; Se ad esempio c'è del testo riconoscibile subito prima o subito dopo il titolo che si può cercare facilmente, si può provare a trovare il titolo nelle linee sopra o sotto di esso.

Ad ogni modo, una volta che l'avete trovato, risalite nel file FO finchè non si trova l'inizio della sezione, spesso identificabile con un numero di id autogenerato:

</fo:block>
<fo:block id="d0e2340">
  <fo:block>
    <fo:block>
      <fo:block keep-together="always" margin-left="0pc"
                font-family="sans-serif,Symbol,ZapfDingbats">
        <fo:block keep-with-next.within-column="always">
          <fo:block font-family="sans-serif" font-weight="bold"
                    keep-with-next.within-column="always"
                    space-before.minimum="0.8em" space-before.optimum...
                    space-before.maximum="1.2em" color="#404090" hyph...
                    text-align="start">
            <fo:block font-size="11pt" font-style="italic"
                      space-before.minimum="0.88em" space-before.opti...
                      space-before.maximum="1.32em">The DISTINCT keyword
              comes to the rescue!</fo:block>

Come si può vedere, ci possono essere un bel po' di righe tra l'inizio della sezione ed il titolo del testo. Notare, inoltre, come il titolo qui è diviso su due linee.

Una volta identificato il fo:block che corrisponde all'inizio della sezione, basta mettergli un attributo break-before="page" proprio come si è fatto prima.

Perchè risalire e cercare l'inizio della sezione e non mettere il break-before al fo:block che racchiude direttamente il titolo? Be', perchè stamperà sì il titolo nella pagina successiva, giustamente, ma i link nel frame di navigazione e nell'indice punteranno (oibò!) alla pagina precedente, perchè la (invisibile) sezione inizia - cioè il blocco che ha l'ID - prima del salto pagina forzato.

Spazi nei nomi di file, URL ecc.

Problema: Spazi (di dimensione variabile) appaiono in certe posizioni nei nomi di file ecc.

Causa: Nel file FO, questi elementi contengono caratteri spazio di dimensione zero ( zero-width space o ZWSP, Unicode 200B esadecimale) per indicare dove la stringa può essere interrotta per andare a capo. Sfortunatamente, Apache FOP utilizza gli stessi caratteri anche ai fini della giustificazione.

Soluzione: Se gli spazi sono proprio troppo grandi, si possono eliminare (tranne quando la linea deve effettivamente andare a capo dove c'è quel ZWSP).

Come: Cercare l'intera URL o nome del file non può funzionare, proprio perchè la stringhe contiene i famosi spazi di lunghezza zero! Se la stringa contiene un elemento che è raro o unico nel file (es. hababarulala nel nome di file C:\Strips\Pintoplaneet\hababarulala.txt), si potrebbe usare quello. Altrimenti si cerca per del testo che gli stà vicino. (Ormai si è capito che a scorrere semplicemente il file FO ci si impiega troppo, a causa della gran quantità di cose in più introdotte dal XSL-FO, invadendo tutto il testo del documento)

Una volta trovata la stringa, controllare se si riesce effettivamente a vedere gli spazi ZWSP. Alcuni editor non li mostrano per niente (il che sarebbe anche giustificato, dato che hanno dimensione zero). Comunque, si dovrebbe essere in grado di trovarli scorrendo la stringa con il cursore. Se con la freccia a destra o a sinistra il cursore non si muove (ma torna a muoversi con il successivo movimento nella stessa direzione), quello è il punto dov'è lo ZWSP. Altri editor li mostrano con un simbolo, altri (ConText) come tre “strani”caratteri: ​. Questi caratteri rappresentano il codice a tre byte UTF-8 per lo spazio di dimensione zero.

Se si riesce ad indentificare lo spazio di dimensione zero, si può cancellare, ma bisogna tenere d'occhio pure il file PDF: non bisogna eliminare uno ZWSP se serve per andare a capo nel PDF.

Righe di tabella interrotte

Problema: In una tabella, una riga è interrotta da un salto pagina per cui non è tutta da una parte o dall'altra.

Causa: Nessuna in particolare - non c'è una regola che impedisca i salti pagina all'interno delle righe di una tabella.

Soluzione: Per tenere la riga insieme, inserire un salto pagina all'inizio della riga.

Come: Cerca la riga sulla base del testo all'inizio della riga o alla fine della riga precedente. L'elemento che si sta cercando è fo:table-row, ma non si deve usare come stringa di ricerca, perchè molti elementi di DocBook (non solo per le tabelle, cioè gli elementi <table>) sono implementati usando fo:table e pertanto contengono fo:table-rows.

Una volta trovato l'inizio della riga tagliata a metà, si aggiunge un attributo break-before esattamente come per i windowed headers:

<fo:table-row break-before="page">

In alternativa si può sempre impostare un attributo break-after alla riga precedente.

Spazi orizzontali enormemente larghi

Problema: Spazi molto larghi per giustificare linee precedenti lunghe stringhe senza spazi. Queste stringhe lunghe sono spesso stampate con font a spazio fisso:

Causa: Apache FOP spesso non sillaba queste stringhe e le prende come un tutt'uno. Pertanto, se la stringa non entra nella riga la sposta interamente nella riga seguente. Questo lascia alla linea precedente “troppo poco” testo, rendendo necessaria una giustificazione con larghi spazi. Notare come nell'esempio qui sopra, gli spazi nella linea sopra siano causati dall'incapacita di suddividere la stringa della linea successiva, e non dal contenuto della linea precedente stessa.

Soluzione: Ci potrebbero essere buone ragioni per non suddividere la stringa. In quel caso ci si adatta ai larghi spazi facendo buon viso a cattivo gioco. Altrimenti si inserisce uno spazio (oppure il carattere '-' seguito da uno spazio) al punto dove si desidera separare la stringa.

Come: Prima bisogna trovare la stringa nel file FO cercando il (o parte del) suo contenuto. Se è una stringa a spazio fisso nel PDF, molto probabilmente la si dovrebbe trovare in un elemento fo:inline. Poi, si osserva nel PDF per valutare quanta parte della stringa ancora ininterrotta entrerebbe nello spazio rimasto della linea precedente. Di nuovo nel file FO, si inserisce uno spazio, possibilmente preceduto da un “-”, nella stringa al punto in cui sembra accettabile mandarla a capo. Rigenerare il PDF (build fo2pdf !) e verificare il risultato. Se si è interrotta la stringa troppo a destra, rimane ancora tutta nella linea successiva. Troppo a sinistra e lo spazio potrebbe rimane ancora troppo largo rispetto alle proprie intenzioni. Si continua a sistemare e a ricostruire finchè non si ottiene l'aspetto desiderato.

Durante questo procedimento, si potrebbe essere sorpresi dal fatto che, una volta interrotta la stringa in un punto, Apache FOP autonomamente decide di sillabare il resto della stringa. Questo lascia una parte della stringa nella linea precedente con lo spazio aggiunto (adesso nel posto sbagliato) perchè prosegue oltre quel punto. Non resta che cancellare lo spazio che si è aggiunto e interrompere la stringa nel punto deciso da Apache.

Inserire spazi di dimensione zero

Una soluzione alternativa al problema degli spazi enormi sarebbe inserire spazi di dimensione zero proprio in tutti i punti in cui la stringa in esame potrebbe essere mandata a capo, lasciando decidere Apache FOP quale è il più adatto. Questo funziona sicuramente al primo tentativo, ma:

  • si può fare solo avendo un editor che permette di inserire facilmente gli ZWSP;

  • funziona solo dove è possibile interrompere la stringa senza il “-”;

  • potrebbe generare spazi indesiderati dove sono stati messi gli ZWSP (vedi sopra), costringendo a cancellarli tutti tranne quello che risolve veramente il problema.

Riferimenti su XSL-FO

La pagina web uffilciale di XSL-FO (Formatting Objects) è qui: http://www.w3.org/TR/xsl/

La pagina di Apache FOP è qui: http://xmlgraphics.apache.org/fop/

La pagina di adeguamento di Apache FOP è qui: http://xmlgraphics.apache.org/fop/compliance.html. Contiene una grande tabella di supporto agli oggetti in cui si può verificare quali oggetti ed attributi (proprietà) XSL-FO sono supportati. Consultando la tabella, si tenga presente che attualmente si sta adoperando Apache FOP 0.20.5.

Indietro: Se qualcosa non vaPartenza: Documenti FirebirdRisali: Come fare il manuale di FirebirdAvanti: Revisioni
Documenti FirebirdAgli scrittori per FirebirdCome fare il manuale di Firebird → Avanzato: perfezionare i PDF