Una Chiave per il Desktop Publishing

Corso di PostScript - Marco A. Calamari

Quarta Puntata


In questa puntata, quasi interamente dedicata agli operatori grafici, approfondiremo i principali metodi per tracciare immagini in PostScript. Saranno introdotti i concetti di sistema di riferimento e di stato grafico,che verranno utilizzati in esempi applicativi; sarà inoltre introdotto il concetto di incapsulamento di un programma PostScript.


Dato che il PostScript è un linguaggio specializzato per la grafica, è necessario comprendere a fondo il funzionamento degli operatori grafici, in modo da farne l'uso migliore. Dedicheremo quindi tutta questa puntata ad una descrizione dettagliata dell'utilizzo di questo tipo di operatori .

Prima di introdurre l'elenco dei nuovi operatori PostScript che impiegheremo in questa e nelle prossime puntate, è necessario introdurre un concetto fondamentale del linguaggio PostScript, quello di stato grafico.

Cos'è uno stato grafico

Lo stato grafico dell'interprete PostScript è rappresentato dal valore di alcune variabili e dal contenuto di oggetti che controllano importanti dettagli del funzionamento degli operatori grafici. I componenti dello stato grafico, ed i relativi valori di default (attivi al momento dell'accensione della periferica) sono:

Questa lista è divisa in tre parti. La prima include cose che sono già note, e che non dovrebbero quindi creare problemi, la seconda quei parametri che saranno trattati in questa puntata, ed infine la terza quelli che saranno introdotti nel seguito del corso.

Da un semplice esame dei nomi dei parametri che caratterizzano lo stato grafico, e dei relativi operatori, che sono noti od inclusi nell'elenco di questa puntata, potete constatare che il nome dell'operatore che assegna il valore ad un parametro (per esempio il tono di grigio gray) si ottiene aggiungendo il prefisso set al nome del parametro (setgray). Analogamente, il nome dell'operatore che restituisce il valore corrente di un parametro (di nuovo il tono di grigio gray) si ottiene aggiungendo il prefisso current al nome del parametro (currentgray). C'è una eccezione a questa regola, costituita dal punto corrente point; infatti, mentre il comando che restituisce le coordinate del punto corrente è currentpoint, il comando setpoint non esiste; infatti l'operatore che definisce il punto corrente è semplicemente moveto.

Ma che cosa rende il concetto di stato grafico più di una definizione astratta, utile tuttalpiù per definire lo stato iniziale dell'interprete PostScript, e lo trasforma in un potente strumento di programmazione ? Vediamo un poco. Tipicamente un documento consiste di parecchie pagine, ciascuna delle quali può contenere un misto di grafica e testo; il caso più semplice è quello di un documento con figure. Per poter definire una figura, sarà probabilmente necessario spostare l'origine del sistema di riferimento della pagina nell'angolo in basso a sinistra dell'illustrazione, ridurre la scala di un fattore opportuno, ed estendere queste operazioni a tutti gli elementi grafici contenuti nell'illustrazione; il discorso dovrà poi essere ripetuto per eventuali altre illustrazioni presenti nella pagina, ed infine dovranno essere ripristinate le condizioni iniziali, per poter stampare il testo e passare alla pagina seguente.

Gestire tutto questo con variabili PostScript che ricordino i valori precedenti di tutti i parametri dello stato grafico sarebbe macchinoso e poco intuitivo, e richiederebbe un notevole lavoro di programmazione; nel caso poi di utilizzo della modalità interattiva del PostScript (executive), questo modo di lavorare sarebbe ingestibile.

L'interprete PostScript fornisce una eccellente soluzione a tutti questi problemi; l'utilizzo di uno stack dedicato, lo stack degli stati grafici, e dei relativi operatori gsave e grestore. Utilizzando questi operatori, è possibile salvare in ogni momento lo stato di tutti i parametri grafici in un oggetto di tipo save, che viene automaticamente posto su un apposito stack, analogo nel funzionamento a quelli degli operandi e dei dizionari, ma da essi completamente separato. È poi possibile fare tutti i cambiamenti necessari allo stato grafico, eseguire le operazioni desiderate, e ripristinare lo stato precedente con il comando grestore. Ovviamente è possibile salvare più di uno stato grafico, valendosi del fatto che vengono memorizzati su uno stack.

Il sistema di coordinate

Una delle cose più importanti contenute nello stato grafico, e che viene salvata o ripristinata insieme ad esso è la CTM (Current Transformation Matrix - matrice di trasformazione corrente); la CTM mette in corrispondenza le coordinate del sistema di riferimento che utilizziamo (x, y) con quelle fisiche della pagina in memoria (x', y'). Si tratta quindi in sostanza del sistema di assi che utilizziamo per tracciare la grafica ed il testo che dovranno apparire nella pagina. Le equazioni che descrivono la trasformazione sono

x' = a*x + c*y + h

y' = b*x + d*y + k

e la matrice CTM può essere definita, usando la notazione PostScript come

[ a b c d h k ]

La matrice di default dipende dal device utilizzato; quella attiva all'accensione della LaserWriter è la seguente

[4.16667 0.0 0.0 -4.16667 -72.0 3416.0 ]

la quale mette in corrispondenza esatta i sistemi di coordinate dell'utente (72 punti/pollice ed origine in basso a sinistra), con quello del device (nel caso della LaserWriter 300 punti/pollice ), infatti 300/72=4.16667; nella maggior parte dei casi potremo comunque pensare che essa sia la matrice unitaria

[ 1 0 0 1 0 0 ]

immaginando che il sistema di coordinate della pagina sia quello del device. Quando utilizziamo gli operatori rotate, translate e scale, non facciamo altro che agire opportunamente, ma in maniera indiretta, sulla CTM; esistono poi anche operatori che permettono di agire direttamente sulla CTM, producendo trasformazioni di tipo più generale dei precedenti.

Alcuni degli operatori di trasformazione del sistema di riferimento sono usati nel programma del Listato 1, il cui output è mostrato in Figura 1.

Linecap, dash e linejoin

Durante l'uso dell'operatore stroke, possono essere ottenuti effetti molto diversi a seconda del valore corrente di alcuni parametri dello stato grafico, che sono i seguenti:

- il tipo di estremità della linea (linecap), che può essere normale, cioè tagliato nelle estremità, arrotondato prolungando la linea con una semicirconferenza di diametro pari allo spessore della linea, o esteso prolungando la linea di una lunghezza pari a metà spessore;

- il tipo di tratteggio da applicare alla linea (dash), che viene definito con un apposito vettore che descrive le ampiezze dei tratti e degli spazi nell'unità di misura attiva al momento, e che viene ripetuto il numero di volte necessario;

- il tipo di angolo fra due segmenti (linejoin), che può essere arrotondato, smussato od a spigolo vivo.

Si noti che i valori che vengono utilizzati per tracciare la path non sono quelli attivi al momento della definizione del segmento interessato, ma quelli attivi quando viene eseguito l'operatore stroke.

Gli operatori che modificano i parametri dello stato grafico sopra elencati vengono utilizzati nel programma del Listato 2, il cui output è mostrato in Figura 2.

La clipping path

Una potente strumento grafico dell'interprete PostScript è la clipping path; questa entità permette di delimitare la parte dell'immagine che viene tracciata sulla pagina in memoria quando vengono utilizzati operatori come stroke, fill o show. Il valore di default di tale entità e ovviamente pari al perimetro rettangolare della massima area utilizzabile; nel caso di una LaserWriter è circa mezzo pollice più piccola di una pagina formato A4.

In questa condizione l'effetto della clipping path non è visibile. Con l'utilizzo degli opportuni operatori è però possibile modificare la clipping path di default, restringendola all'area contenuta da una curva chiusa arbitraria, la quale può anche essere intrecciata o costituita da più regioni separate. Un esempio dell'utilizzo degli operatori che modificano la clipping path è costituito dal programma del Listato 3, il cui output è mostrato in Figura 3; in tale esempio viene utilizzato un operatore (for) che non è ancora stato definito, ma che serve ovviamente per ripetere un certo numero di volte una certa sequenza di istruzioni, ed appartiene alla categoria degli operatori di controllo del flusso di programma, che saranno introdotti nella prossima puntata.

Introduciamo ora l'elenco dei nuovi operatori PostScript, divisi per tipologia, che dovrà ovviamente essere utilizzato anche per esaminare il funzionamento degli esempi proposti.

Operatori Grafici - sistema di coordinate

Operatori Grafici - stati grafici

Operatori Grafici - path

Il concetto di incapsulamento

Prima di concludere, è opportuno introdurre un concetto che verrà meglio precisato in futuro, e che è una delle linee guida per la programmazione in PostScript; quello di incapsulamento.

Incapsulamento significa che ogni parte di programmi, procedure, descrizioni di singole pagine di un documento, illustrazioni e così via, non deve alterare lo stato grafico che era presente all'inizio; nel caso che ciò sia necessario, deve salvarlo prima e ripristinarlo poi, utilizzando gli operatori gsave e grestore. Questo permette di prendere una singola procedura o anche l'intero programma, e utilizzarlo come parte di un programma più ampio senza la necessità di modifiche. Un timido tentativo in questa direzione è rappresentato dagli esempi di questa puntata, e dalla procedure tracciaCornice in essi utilizzata.

Esercizio

Per verificare il grado di confidenza raggiunto nell'utilizzo degli operatori grafici vi proponiamo un esercizio; modificate il terzo esempio in modo che lo spazio compreso fra la cornice ed il profilo delle lettere PS sia di un grigio molto chiaro, mentre l'interno delle lettere rimanga bianco. Un consiglio; durante le vostre prove commentate provvisoriamente il loop for che scrive ripetutamente la parola PostScript, al fine di risparmiare tempo.

Una possibile soluzione dell'esercizio proposto verrà ovviamente fornita nella prossima puntata, nella quale introdurremo anche gli operatori di controllo del PostScript, e preciseremo ulteriormente il concetto di incapsulamento, definendo il concetto di programmi conformi ed il loro utilizzo.


% Corso PostScript - IV parte - programma 1
% Utilizzo degli operatori di trasformazione
% del sistema di coordinate
%
% Procedura inch
% Argomenti: XInches / XPoints
% Converte misure da pollici
% a punti tipografici.
/inch { 72 mul } def
%
% Procedura tracciaCornice
% Argomenti: - / -
% Traccia una cornice su pagina
% A4 a mezzo pollice dal margine.
/tracciaCornice {
gsave newpath
0.5 inch 0.5 inch moveto
7.3 inch 0 inch rlineto
0 inch 10.5 inch rlineto
-7.3 inch 0 inch rlineto
closepath
.05 inch setlinewidth
0 setgray stroke
grestore
} def
%
% Procedura stampaParola
% Argomenti: - / -
% Stampa la parola ABC partendo sempre dalla
% origine del sistema di riferimento, scrivendo
% nella direzione dell'asse X.
/stampaParola { 0 0 moveto (ABC) show} def
%
% Programma principale
% Viene tracciata la cornice della pagina
tracciaCornice
%
% Viene definitp e scalato il font da usare
/Times-Bold findfont 100 scalefont setfont
%
% Poiché il programma modifica lo stato grafico,
% lo si incapsula tra gsave e grestore
gsave
%
% Sposta l'origine di 1.5 pollici in alto e a destra
% e stampa la stringa ABC
1.5 inch 1.5 inch translate stampaParola
%
% Sposta di nuovo l'origine di 1.5 pollici in alto
% e a destra, e stampa nuovamente ABC
1.5 inch 1.5 inch translate stampaParola
%
% Sposta di nuovo l'origine di 1.5 pollici in alto
% e a destra, ruota gli assi di 60 gradi
% e stampa nuovamente ABC
1.5 inch 1.5 inch translate 60 rotate stampaParola
%
% Sposta di nuovo l'origine di 1.5 pollici in alto
% e a destra (rispetto al sistema di riferimento
% ruotato), allunga del 50% la scala sull'asse X,
% accorcia del 50% quella sull'asse Y e stampa
% nuovamente ABC
1.5 inch 1.5 inch translate 1.5 0.5 scale stampaParola
%
% Si ripristina lo stato grafico
grestore
%
% Stampa la pagina
showpage

% Corso PostScript - IV parte - programma 2
% Esempio di diversi linejoin, linecap e dash
%
% Procedura inch
% Argomenti: XInches / XPoints
% Converte misure da pollici
% a punti tipografici.
/inch { 72 mul } def
%
% Procedura tracciaCornice
% Argomenti: - / -
% Traccia una cornice su pagina
% A4 a mezzo pollice dal margine.
/tracciaCornice {
gsave newpath
0.5 inch 0.5 inch moveto
7.3 inch 0 inch rlineto
0 inch 10.5 inch rlineto
-7.3 inch 0 inch rlineto
closepath
.05 inch setlinewidth
0 setgray stroke
grestore
} def
%
% Procedura tracciaLinea
% Argomenti: X1 Y1 X2 Y2 / -
/tracciaLinea {
4 -2 roll moveto lineto stroke
} def
%
% Programma principale
% Viene tracciata la cornice della pagina
tracciaCornice
%
% Incapsulamento
gsave
%
% Trasla l'origine di 0.5 pollici a destra e 1 pollice
% in basso, e quadruplica la scala sugli assi
0.5 inch -1.0 inch translate 4 4 scale
%
% Traccia la linea di riferimento di spessore 1
0.4 inch 2.5 inch 1.0 inch 2.5 inch tracciaLinea
%
% Porta lo spessore a 6
6 setlinewidth
%
% Traccia tre linee con linecap 2, 1, 0
2 setlinecap
0.4 inch 2.2 inch 1.0 inch 2.2 inch tracciaLinea
1 setlinecap
0.4 inch 1.9 inch 1.0 inch 1.9 inch tracciaLinea
0 setlinecap
0.4 inch 1.6 inch 1.0 inch 1.6 inch tracciaLinea
%
% Porta lo spessore a 1
1 setlinewidth
%
% Traccia tre linee con diversi tratteggi
[ 6 3 ] 0 setdash
0.4 inch 1.3 inch 1.0 inch 1.3 inch tracciaLinea
[ 6 3 ] 3 setdash
0.4 inch 1.0 inch 1.0 inch 1.0 inch tracciaLinea
[ 5 3 1 3 ] 0 setdash
0.4 inch 0.7 inch 1.0 inch 0.7 inch tracciaLinea
%
% Riporta il tratteggio a linea continua
[] 0 setdash 6 setlinewidth
%
% Traccia tre angoli con linejoin 0, 1, 2
0 setlinejoin 1.5 inch 1.3 inch moveto
1.2 inch 1.3 inch lineto
1.4 inch 1.5 inch lineto stroke
1 setlinejoin 1.5 inch 1.0 inch moveto
1.2 inch 1.0 inch lineto
1.4 inch 1.2 inch lineto stroke
2 setlinejoin 1.5 inch 0.7 inch moveto
1.2 inch 0.7 inch lineto
1.4 inch 0.9 inch lineto stroke
%
% Rimozione incapsulamento
grestore
%
% Stampa pagina
showpage

% Corso PostScript - IV parte - programma 3
% Esempio di utilizzo dell'operatore clip
% Questo programma impiega circa 10 minuti
% su una LaserWriter Plus; abbiate pazienza e
% non resettatela subito, specialmente se la
% luce gialla lampeggia ancora.
%
% Procedura inch
% Argomenti: XInches / XPoints
% Converte misure da pollici
% a punti tipografici.
/inch { 72 mul } def
%
% Procedura tracciaCornice
% Argomenti: - / -
% Traccia una cornice su pagina
% A4 a mezzo pollice dal margine.
/tracciaCornice {
gsave newpath
0.5 inch 0.5 inch moveto
7.3 inch 0 inch rlineto
0 inch 10.5 inch rlineto
-7.3 inch 0 inch rlineto
closepath
.05 inch setlinewidth
0 setgray stroke
grestore
} def
%
% Programma principale
% Viene tracciata la cornice della pagina
tracciaCornice
%
% Incapsulamento
gsave
%
% Raddoppia la scala sugli assi e pone flat=2
2 2 scale
4.0 setflat
%
% Definisce le variabili globali X e Y
/X .5 inch def /Y 2.5 inch def
%
% Sposta il punto corrente a X,Y
X Y moveto
%
% Definisce il font corrente come
% Times-Bold a corpo 200
/Times-Bold findfont 200 scalefont setfont
%
% Definisce la path corrente uguale al
% contorno delle lettere PS
(PS) true charpath
%
% Salvo lo stato grafico (per salvare la path
% corrente), la traccia sulla pagina ed infine
% ripristina lo stato grafico
gsave stroke grestore
%
% Definisce la clipping path uguale al
% contorno delle lettere PS
clip
%
% Annulla la path corrente (clip non lo fa)
newpath
%
% Definisce il font corrente come
% Times-Roman a corpo 7
/Times-Roman findfont 7 scalefont setfont
%
% Riempie la clipping path precedentemente
% definita con un pattern formato dalla parola
% PostScript, ottenuto utilizzando un ciclo
% per mezzo dell'operatore for, il quale ripete
% la procedura fra parentesi graffe, ponendo ogni
% volta il contatore aggiornato sullo stack, per
% i valori da 0 a 136 a passi di 8.
0 8 136
{ Y add X exch moveto
(PostScript PostScript PostScript PostScript\
PostScript PostScript PostScript PostScript ) show }
for
%
% Rimozione incapsulamento
grestore
%
% Stampa pagina
showpage

Copyright © 1985: Marco A. Calamari