Firebird Documentation IndexCome fare il manuale di Firebird → Avanzato: perfezionare i PDF
Firebird Home Firebird Home Indietro: Se qualcosa non vaFirebird Documentation IndexRisali: 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 affrontare questi problemi, 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 -Did=qsg15

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

build fo2pdf -Did=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. Per fortuna, sono diventate rarissime da quando abbiamo adottato la versione FOP 0.93.

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 da nessuna parte l'attributo keep-with-next (mantieni con successivo).

Nota

Da quando si è aggiornato il sistema all'uso di Apache FOP 0.93, questo noiosissimo problema è diventato estremamente raro. Tuttavia in alcuni rari casi può ancora accadere. Oppure, più in generale, potrebbe esserci un salto pagina che sembra fastidioso, ad esempio dopo una linea che annuncia un seguito e finisce con due punti. Questa sezione aiuta a risolvere questi casi.

Notare che l'esempio che qui viene esemplificato, cioè una testata di sezione vedova, non dovrebbe più succedere, ma è utile per mostrare i passi da prendere, specialmente per gli elementi che hanno un attributo id.

Soluzione: Forzare un salto pagina all'inizio dell'elemento (tipicamente una lista, un elemento di lista o una tabella) 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:

<fo:bookmark starting-state="hide"
             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.

Quando manca il DocBook ID

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è ciò 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.

Come già detto, il problema delle testate vedove non dovrebbe più accadere con le sezioni, ma potrebbe presentarsi con qualche altro tipo d'oggetto, come le tabelle o le figure. In tutti questi casi si possono usare le tecniche illustrate qui sopra.

Inoltre, ci sono molti elementi DocBook (di fatto, la maggior parte) per i quali i fogli di stile non generano ID. Esempi sono para, informaltable, i vari tipi di liste, ecc. In tali casi, una volta trovato il frammento di testo del file FO, si tratta di applicare semplicemente l'attributo break-before al più vicino fo:block che ha un ID.

Righe di tabella o di elementi in lista interrotti

Problema: In una tabella, una riga è interrotta da un salto pagina per cui non è tutta da una parte o dall'altra. Lo stesso dicasi per gli elementi di una lista.

Causa: Nessuna in particolare - non c'è una regola che impedisca i salti pagina in questi casi particolari.

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 orrizontali 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 a queste condizioni:

  • avendo un editor che permette di inserire facilmente gli ZWSP;

  • dove è possibile interrompere la stringa senza il «-»;

Contenuti di pagina compressi, troncati o scombussolati in un qualche altro modo

Problema: Tabelle, figure o altri oggetti formali vengono spiaccicati oppure alcune loro parti sono stampate sopra altre.

Causa: Agli oggetti formali viene dato un un attributo nel foglio di stile keep-together.within-page="always" (mantieni insieme nella pagina sempre). Con FOP 0.93, questo attributo è sempre forzato, anche se l'oggetto è troppo grande per stare in una pagina. Il risultato: il contenuto distrutto è strizzato tutto dentro la pagina.

Soluzione: Ci sono tre alternative. 1: Usare il corrispondente elemento DocBook informale. 2: Inserire una elaborazione di istruzioni nel sorgente DocBook. 3: Rimuovere l'attributo dal sorgente FO.

Come: Due soluzioni sono applicate al sorgente DocBook, la terza implica la modifica del file FO:

  • Se non si vuole lasciare gli elementi senza titolo, si può usare informalequation / informalexample / informalfigure / informaltable invece delle loro controparti formali, rispettivamente, equation, example, figure e table. Questi elementi non prendono l'attributo keep-together nella trasformazione, in tal modo il salto pagina viene all'interno dell'elemento.

  • Se riguarda una tabella, volendo mantenere il titolo, si può inserire una elaborazione di istruzioni (processing instruction) come questa:

    <table frame="all" id="ufb-about-tbl-features">
      <?dbfo keep-together='auto'?>
      <title>Summary of features</title>
      ...
      (table content...)
      ...
    </table>

    Aggiungere l'istruzione modificando il codice sorgente è abbastanza semplice. Con XMLMind, è un pochino più laborioso:

    1. Mettere il cursore da qualche parte del titolo o selezionare tutto l'elemento del titolo.

    2. Scegliere Modifica -> Elabora Istruzione -> Inserisci Istruzione di Elaborazione Prima dal menù. Apparirà sopra il titolo una linea, di solito verde ma ciò dipende dai colori scelti.

    3. Digitare keep-together='auto' su quella linea.

    4. Con il cursore ancora su quella linea, scegliere Modifica -> Inserisci Istruzione di Elaborazione -> Cambia l'Obiettivo dell'Istruzione di Elaborazione dal menu. Si apre una finestra di dialogo.

    5. Nella finestra di dialogo, modificare la parola target in dbfo e cliccare su OK.

    A proposito, si può fare l'opposto con una informaltable se si desidera assolutamente che non venga interrotta da un salto pagina. La procedura è identica, eccetto che si deve specificare always invece di auto. Ovviamente bisogna essere più che sicuri che la informaltable ci stia nella pagina!

    Non sono stati previste soluzioni similari per altri oggetti formali perchè probabilmente non ce ne sarà mai bisogno. Cose di questo genere richiedono molto lavoro nei nostri fogli di stile personalizzati, pertanto li implementeremmo solo in caso di reale necessità.

  • L'ultima risorsa è mettere mano al file fo... pertanto, aprire il file FO, trovare l'elemento (suggerimento: dargli un id nel sorgente DocBook per trovarlo facile facile) e togliere l'attributo keep-together.within-page="always". Lo svantaggio, già si sa, è che bisogna rifarlo tutte le volte che si cambia il sorgente e viene costruito un nuovo PDF. Le altre soluzioni sono invece durature.

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.93 (con alcune modifiche).

Indietro: Se qualcosa non vaFirebird Documentation IndexRisali: Come fare il manuale di FirebirdAvanti: Revisioni
Firebird Documentation IndexCome fare il manuale di Firebird → Avanzato: perfezionare i PDF