MokaByte Numero 25  -  Dicembre 98
Java 2D API 
di 
Massimo Carli
Un nuovo insieme di strumenti a supporto della grafica 2D in Java - I parte.






 

Come da tempo annunciato, iniziamo questo mese, un corso sulle nuove Java2D API che offrono un insieme di nuovi strumenti a supporto della grafica 2D in Java. In questo primo mese daremo una descrizione di quelle che sono le nuove caratteristiche introdotte e di quelle che sono le nuove potenzialità offerte da questi nuovi strumenti. Dal mese prossimo, inizieremo ad approfondire ogni singola caratteristica. Per seguire questo corso non servono particolari conoscenze di programmazione Java, né conoscenze relative alla grafica bidimensionale. Ogni aspetto verrà spiegato ed opportunamente approfondito durante il corso. 

 

Le Java2D

Le Java2D API fanno parte di quelle che si chiamano JFC (Java Foundation Classes ) che comprendono anche le Swing, l'accessibility e la gestione del Drag And Drop. Nel JDK1.1 per disegnare particolari forme geometriche si utilizzano gli strumenti offerti dall'oggetto java.awt.Graphics ottenuto solitamente come parametro del metodo paint(Graphics g). La variabile di tipo java.awt.Graphics, che solitamente si indica con g, si chiama contesto grafico e permette di memorizzare lo stato di alcune dimensioni grafiche quali il colore o il font corrente. Attraverso opportuni metodi è possibile disegnare le forme geometriche più semplici quali i punti, le linee, i rettangoli ed i poligoni in generale. La piccola rivoluzione fatta dalle Java2D API è l'introduzione della nuova classe java.awt.Graphics2D che, estendendo la java.awt.Graphics, oltre a fornire nuovi strumenti, permette di gestire la grafica con un approccio diverso. Con le nuove Java2D API la realizzazione di un particolare disegno si può scomporre nelle seguenti fasi:

    Creazione delle forme da visualizzare

    Impostazione delle proprietà relative al modo con cui le varie forme devono essere visualizzate

    Impostazione delle proprietà relative al modo cui le varie forme interagiscono tra loro.

    Applicazione di particolari trasformazioni

    Impostazione delle proprietà di rendering

    Rendering


 

Gestione delle forme da visualizzare

Ogni oggetto di cui sarà fatto il rendering (visualizzato in modo opportuno) implementerà l'interfaccia Shape del package java.awt. Questa interfaccia prevede la definizione di un insieme di metodi che permettono di conoscere il rettangolo contenitore della particolare forma geometrica e che permettono di verificare se un particolare punto (x,y) gli appartiene. Per la visualizzazione di una particolare regione non è necessario infatti sapere i valori di tutti i punti (x,y) che la compongono ma è sufficiente conoscere la regola per poter dire se un generico punto (x,y) è parte della figura o meno. L'interfaccia java.awt.Shape descrive i metodi per ottenere queste informazioni. L'interfaccia Shape fornisce anche le informazioni relative a quello che si chiama PathIterator rappresentato dalla omonima classe del nuovo package java.awt.geom. Questa classe rappresenta un modo con cui a partire da un elemento di una curva (un segmento) si ottenga il segmento seguente. In questo modo si ottiene, secondo una regola che dipende dal particolare PathIterator, una qualunque curva. Il nuovo package java.awt.geom contiene quindi tutte le classi relative alle forme geometriche più comuni ma non solo, contiene anche le classi per la rappresentazione di particolari curve ottenute con particolari PathIterator. Lo studio di queste forme geometriche sarà argomento della prossima puntata del corso.
Per forme da visualizzare si intendono anche quelle ottenute da porzioni di testo. Nel JDK1.1 le caratteristiche di visualizzazione del testo sono trattate in modo semplice attraverso la definizione della classe java.awt.Font che memorizza le informazioni relative ad un particolare set di caratteri. Con le Java2D API si ha un grosso cambiamento nella gestione del testo. Diciamo solamente che si ha la definizione di quelli che si chiamano Glyph (letteralmente geroglifici o segni) che compongono ciascun carattere. Fino ad ora vi era una corrispondenza biunivoca tra una lettera dell'alfabeto ed un simbolo grafico. Adesso questa corrispondenza non si utilizza più in quanto un particolare font è costituito da un insieme di glyph che è solitamente maggiore del numero di caratteri e che rappresenta l'insieme dei simboli che permettono la scrittura. Un esempio potrebbe essere quello di un font che rappresenta il corsivo. Una lettera non è scritta sempre nello stesso modo ma dipende dalle lettere che lo precedono e seguono. Si tratterà allora di scomporre ciascun carattere in uno o più glyph e costruire la rappresentazione grafica della stringa nel modo opportuno. La parte dedicata alla gestione del testo avrà molto spazio all'interno del corso. Altra cosa importante riguarda il fatto che da ciascun glyph è possibile ottenere la corrispondente Shape. Questo permette di considerare del testo come una qualunque altra figura geometrica cosa finora impossibile in Java.

Impostazione del modo di visualizzazione delle Shape

Abbiamo visto che le Java2D API ci permettono di trattare ogni oggetto come una Shape. E' possibile definire il modo con cui queste Shape saranno visualizzate ovvero è possibile decidere le caratteristiche ed il colore delle linee. Questo è fatto attraverso oggetti che implementano l'interfaccia java.awt.Stroke. Questa nuova interfaccia descrive il metodo che permette, a partire da una Shape, di ottenere la Shape che sarà visualizzata. Una implementazione di questa interfaccia è data dalla classe java.awt.BasicStroke che permette di decidere la larghezza di ogni singola linea ed il comportamento delle linee quando si congiungono. Durante il nostro corso vedremo nel dettaglio tale classe e ne costruiremo di nuove.




Interazione tra le varie Shape

Le Java2D API permettono di decidere il comportamento da tenere in fase di rendering quando due o più Shape si vengono a sovrapporre sia in termini di linee che in termini di trasparenza. Il livello di sovrapposizione in termini di linee è deciso dal particolare oggetto Stroke mentre il livello di sovrapposizione in termini di trasparenza è deciso attraverso classi che implementano l'interfaccia java.awt.Composite. Questa interfaccia permette di decidere che colore visualizzare in corrispondenza ad una coppia di colori che si andrebbero altrimenti a sovrapporre. Una implementazione di questa proprietà è la classe java.awt.AlphaComposite che tratta appunto la trasparenza il problema in termini di trasparenza. Esiste la possibilità di effettuare operazioni di OR, AND o XOR tra le varie Shape e crearne quindi di nuove attraverso l'applicazione di semplici operazioni logiche a Shape già presenti.




Applicazioni di particolari trasformazioni

 Con le Java2D API è ora possibile applicare particolari trasformazioni all'insieme di forme create in precedenza. Il prossimo mese vedremo che una trasformazione avviene comunque durante la fase di visualizzazione in cui si ha un passaggio da un sistema di riferimento utente ad un sistema di riferimento di visualizzazione. Un particolare tipo di trasformazione è dato dall'oggetto AffineTransform che permette di effettuare una trasformazione bilineare alle forme già create nel contesto grafico Graphics2D. Vedremo questo oggetto nel dettaglio, per ora ricordiamo che una trasformazione bilineare è una trasformazione tra coordinate che permette di mantenere il parallelismo tra due linee. Casi particolari di trasformazioni di questo tipo sono ovviamente le operazioni di traslazione e di rotazione.

Impostazione delle proprietà di rendering

Con il JDK1.1, la tecnica del double-buffering doveva essere implementata utilizzando una immagine di background e disegnando su di essa. Esistevano, però, alcuni problemi relativi al fatto che un oggetto Image non era creato se non esisteva la necessità di visualizzarlo (quante volte siamo incappati nel fatidico java.lang.NullPointerException... ). Con le Java2D API la gestione del double buffering può essere automatizzata. Altra tecnica molto utile è quella relativa all'ALIASING. E' abbastanza noto che la qualità delle curve ottenute con i metodi della classe java.awt.Graphics del JDK1.1 non è delle migliori in quanto si notano quei fastidiosi scalini. Con le nuove API è possibile decidere se utilizzare un rendering che tenga conto dell'aliasing o meno. Nel caso in cui si scelga di utilizzare questi strumenti, si otterranno delle curve più soft che, al costo di una maggiore lentezza di visualizzazione, rendono i disegni sicuramente più piacevoli e professionali.

Rendering

Una volta create le varie forme geometriche, impostate le grandezze relative alle trasformazioni da fare ed alle proprietà di rendering, è possibile passare alla fase di visualizzazione attraverso il metodo draw() che riceve come parametro un oggetto Path. Per impostare le varie proprietà da utilizzare in fase di rendering utilizzeremo una serie di metodi set.
 
 
 

 

Altre caratteristiche

Quelle elencate sono solamente alcune delle caratteristiche delle Java2D API. Durante il presente corso, tratteremo anche argomenti diversi quali l'elaborazione delle immagini ed il supporto alla stampa.
 

Conclusioni

In questa prima puntata abbiamo solamente elencato alcune delle nuove potenzialità offerte dalle nuove Java 2D API. Il prossimo mese tratteremo la gestione delle forme geometriche attraverso la creazione di simpatiche applicazioni.


 
 
 
 
 


MokaByte Web  1998 - www.mokabyte.it 
MokaByte ricerca nuovi collaboratori. Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it