vai alla Homepage di Apogeonline

 



Cos'è OpenPress
Glossario
Linux-FAQ
Documenti:

Open Source Definition

GNU General Public License

La cattedrale e il bazaar

Colonizzare la noosfera

Il calderone magico


Libri:

Italian crackdown

Open Sources

MediaMorfosi

GTK+/GNOME
sviluppo applicazioni


Telematica per la pace

Linux HOWTO: Installazione e configurazione

Linux HOWTO: Networking


Risorse
Feedback
vai alla Homepage di Apogeo Editore

Vai alla homepage di OpenPress

GTK+ / Gnome Sviluppo di Applicazioni


Architettura base del canvas

Questa sezione introduce l'architettura del canvas, incluso l'inserimento dei suoi oggetti all'interno di gruppi, dotati di gerarchia, e il sistema di coordinate utilizzato.

GnomeCanvasGroup

Gli oggetti del canvas vengono organizzati in una struttura ad albero. È possibile raggruppare oggetti, per spostarli in gruppo. L'autore dell'architettura del canvas, Federico Mena Quintero, utilizza come esempio pratico un editor per i diagrammi di circuiti. Ciascun gruppo può contenere dei sotto-gruppi. Per ciascuno di questi, il canvas mantiene uno stack di ordinamento: oggetti che si trovano in alto nello stack oscurano gli oggetti che si trovano in basso.

Per implementare questo, il canvas fornisce un oggetto particolare, chiamato GnomeCanvasGroup. Come suggerisce il nome stesso, un CanvasGroup può raggruppare un serie di oggetti del canvas assieme in modo da manipolare tutti questi come un unico elemento. Un GnomeCanvasGroup è invisibile. Per visualizzare se stesso, visualizza ricorsivamente gli oggetti al suo interno. Quando create un nuovo GnomeCanvas, un gruppo di default, chiamato "root", verrà creato per voi. Tutti gli oggetti del canvas vengono aggiunti all'albero al di sotto del gruppo root. Il widget Canvas dialoga unicamente attraverso il gruppo root. Tutti gli elementi presenti vengono gestiti dall'elemento superiore.

Viene fornita una funzione accessoria per accedere al gruppo root del canvas, mostrata in Figura 1 .

#include <libgnomeui/gnome-canvas.h>

GnomeCanvasGroup* gnome_canvas_root(GnomeCanvas* canvas);

Figura 1. Accessori per il gruppo Root

Gli oggetti devono sempre essere parte di un gruppo. Non esiste un oggetto canvas "orfano". Quando create un oggetto dovete specificare il gruppo di appartenenza. È inoltre possibile cambiare il gruppo dopo la creazione dell'oggetto. Tuttavia, gli oggetti sono permanentemente legati al GnomeCanvas all'interno del quale sono stati creati. Non è possibile scambiare oggetti tra canvas diversi.

Sistemi di coordinate

Molte delle caratteristiche del canvas vengono implementate attraverso una traduzione fra diversi sistemi di coordinate. Gli oggetti del canvas possono essere spostati, ruotati, ridimensionati attraverso trasformazioni affini, descritte in dettaglio più avanti. Ecco i più importanti sistemi di coordinate che vengono utilizzate nel canvas e nella scrittura di oggetti personalizzati:

  • Le coordinate globali sono un sistema di coordinate assoluto. Ad esempio, una coordinata globale si riferisce sempre allo stesso punto del canvas. Queste sono concettualmente infinite e rappresentate tramite un double. Il sistema di coordinate globali è quello reale, di primo livello, non modificabile, canonico. Coerenti con il sistema X Window e GDK, la coordinata Y aumenta spostandosi verso il basso.

  • Le coordinate ad oggetto sono le coordinate utilizzate da particolari oggetti del canvas. Le coordinate ad oggetto esistono poiché ogni oggetto associa una trasformazione affina a queste. Nel caso del GnomeCanvasGroup, questa trasformazione viene applicata al gruppo figlio. Per convertire particolari elementi del gruppo dal sistema di coordinate globali a quello ad oggetto, è necessario applicare la trasformazione all'elemento di primo livello, iniziando dal gruppo root. Come le coordinate globali, le coordinate ad oggetto sono concettualmente infinite.

  • Le coordinate canvas sono le coordinate dei pixel. Mentre le coordinate globali e ad oggetto vengono indicate con numeri in virgola mobile, la coordinate canvas sono rappresentate da numeri interi. Per utilizzare il canvas, dovete specificare una regione di "scroll", che corrisponde ad un rettangolo di spazio, espresso in coordinate globali, visibile all'utente. Le coordinate canvas sono relative a questo rettangolo. Questo sistema di coordinate viene utilizzato anche per rappresentare il fattore di ridimensionamento, costituendo il numero di pixel per unità globale. La conversione da coordinate globali a canvas viene eseguita direttamente dal GnomeCanvas sottraendo le coordinate X e Y della regione di scroll, moltiplicando per il fattore di dimensione e quindi approssimando a un numero intero. Le coordinate canvas (0,0) rappresentano l'angolo in alto a sinistra della regione di scroll.

  • Le coordinate buffer sono le coordinate canvas modificate da un riferimento. Alcune implementazioni degli oggetti del canvas utilizzano queste coordinate durante la visualizzazione. Il canvas fornisce all'oggetto un buffer (che può trattarsi di un GdkDrawable oppure di un buffer RGB, opzione dipendente dalla modalità del canvas). Il canvas fornisce all'oggetto indicazioni su quale regione dello schermo il buffer rappresenta (il buffer viene definito tramite un riferimento X e un riferimento Y, larghezza e altezza). I riferimento X e Y sono espressi in coordinate canvas, equivalenti a (0,0) in coordinate buffer. Per convertire le coordinate canvas a coordinate buffer, sottraete semplicemente il riferimento. Le coordinate buffer sono valide unicamente da (0,0) alla larghezza e altezza massime del buffer.

  • Le coordinate window vengono utilizzate raramente. Il canvas copia eventualmente ciascun buffer temporanee in una GdkWindow (per essere precisi, vengono copiati in un GTK_LAYOUT(canvas)->bin_window). Le coordinate window sono relative a questa GdkWindow. In alcuni rari casi è necessario disegnare la finestra direttamente utilizzando un oggetto canvas, oppure poter rispondere a un evento nella finestra (come il drag-and-drop). È necessario successivamente convertire le coordinate window in uno dei sistemi di coordinate precedentemente descritti.

Quando vengono utilizzati oggetti del canvas preesistenti, gli unici sistemi di coordinate interessati sono quello globale e quello ad oggetto. Quando scrivete un oggetto personalizzato, avrete inoltre necessità di utilizzare le coordinate canvas e buffer.

Esistono due modi per convertire i dati fra i vari sistemi di coordinate. Uno di questi consiste nell'ottenere e utilizzare le trasformazioni affini direttamente, come descritto nella sezione successiva del libro. Il metodo più semplice consiste nell'utilizzare le funzioni fornite appositamente, descritte ne . La conversione tra i sistemi di coordinate canvas e ad oggetto richiede che queste siano convertite prima in coordinate globali come stadio intermedio del processo.

#include <libgnomeui/gnome-canvas.h>

void gnome_canvas_w2c(GnomeCanvas* canvas, double wx, double wy, int* cx, int* cy);

void gnome_canvas_w2c_d(GnomeCanvas* canvas, double wx, double wy, double* cx, double* cy);

void gnome_canvas_c2w(GnomeCanvas* canvas, int cx, int cy, double* wx, double* wy);

void gnome_canvas_item_w2i(GnomeCanvasItem* item, double* x, double* y);

void gnome_canvas_item_i2w(GnomeCanvasItem* item, double* x, double* y);

void gnome_canvas_window_to_world(GnomeCanvas* canvas, double winx, double winy, double* worldx, double* worldy);

void gnome_canvas_world_to_window(GnomeCanvas* canvas, double worldx, double worldy, double* winx, double* winy);

Figura 2. Conversione fra sistemi di coordinate

Trasformazioni affini

Una affinitá è una matrice di trasformazione composta da sei numeri reali che possono essere applicati a una coppia ordinata. A seconda dal contenuto dell'affinitá, il punto può essere:

  • Traslato - spostato a una distanza arbitraria in entrambe le dimensioni.

  • Ruotato per un determinato valore, espresso in gradi.

  • Scalato in base ad un fattore di scala.

Concettualmente, un'affinitá definisce la relazione fra i punti di un piano. Per qualunque punto (A, B), l'affinitá definisce un singolo punto trasformato corrispondente. La corrispondenza è uno-a-uno, quindi utilizzando il punto manipolato è possibile risalire al punto originale.

Le trasformazioni affini possono assumere interessanti proprietà che e rendono utili nella grafica computerizzata. Queste possono essere composite, concatenate oppure moltiplicate (i tre termini sono, in questo contesto, sinonimi). È possibile comporre un qualunque numero di trasformazioni affini per crearne una singola.

libart_lgpl contiene un modulo per la manipolazione delle trasformazioni affini. Queste vengono rappresentate come un array di sei numeri a doppia precisione. Le funzione sono descritte in Figura 3 .

#include <libart_lgpl/art_affine.h>

void art_affine_point(ArtPoint* dst, const ArtPoint* src, const double affine[6]);

void art_affine_invert(double dst_affine[6], const double src_affine[6]);

void art_affine_multiply(double dst[6], const double src1[6], const double src2[6]);

void art_affine_identity(double dst[6]);

void art_affine_scale(double dst[6], double sx, double sy);

void art_affine_rotate(double dst[6], double theta);

void art_affine_translate(double dst[6], double tx, double ty);

int art_affine_rectilinear(const double src[6]);

Figura 3. La manipolazione

art_affine_point() applica una trasformazione affine a un singolo punto, tramite il secondo argomento (src) e il risultato viene copiato nel primo argomento (dst). Un ArtPoint consiste in una struttura molto semplice:


typedef struct _ArtPoint ArtPoint;

struct _ArtPoint {
  double x, y;
};

Una trasformazione affine può essere invertita. Se questa converte un punto nel sistema di coordinate A in punto per il sistema di coordinate B, il suo inverso converte punti dal sistema B al sistema A. art_affiner_invert() riempie il suo primo argomento con l'inverso del secondo.

art_affine_multiply() compone due trasfomazioni afini come descritto precedentemente in questa sezione, posizionando il risultato nel primo argomento.

Sono fornite quattro funzioni per crearle con particolari proprietà.

  • art_affine_identity() crea una trasformazione affine identità. Applicare una identità a un punto non ha alcun effetto.

  • art_affine_rotate() fornisce una trasformazione per ruotare i punti di theta gradi.

  • art_affine_translate() fornisce una trasformazione per traslare i punti tx nella dimensione X e ty nella dimensione Y.

  • art_affine_scale() fornisce una trasformazione per scalare il piano tramite i fattori dimensionali fortni ( un fattore uguale a 1.0 non esegue la scala, inferiore riduce le dimensioni, maggiori espande il piano).

art_affine_rectilinear() restituisce TRUE se la trasformazione ruota rettangoli allineati agli assi in modo che questi restino allienati. Quindi, la funzione restituisce TRUE se la rotazione corrisponde a 0, 90, 180 o 270 gradi.

Potete richiedere al widget canvas di calcolare un affinamento che converta le coordinate fra i vari sistemi presenti. Queste funzioni sono mostrate in Figura 4 . Ciascuna di queste riempie un array che voi gli passate con il tipo di trasformazione richiesto.

#include <libgnomeui/gnome-canvas.h>

void gnome_canvas_item_i2w_affine(GnomeCanvasItem* item, double affine[6]);

void gnome_canvas_item_i2c_affine(GnomeCanvasItem* item, double affine[6]);

void gnome_canvas_w2c_affine(GnomeCanvas* canvas, double affine[6]);

Figura 4. Trasformazioni affini del canvas


Copyright © 1995-1999 Apogeo srl, Milano