Creare una finestra mediante le funzioni del API di SDL

Da Gambas-it.org - Wikipedia.

SDL mette a disposizione alcune librerie contenenti varie funzioni che consentono, fra l'altro, anche la creazione di finestre ove visualizzare testo, immagini ed altro.


Per creare e gestire in modo adeguato le finestre, bisognerà servirsi delle seguenti attuali librerie condivise .so:

  • libSDL-1.2.so.0.11.4 per la gestione generale delle finestre;
  • libSDL_image-1.2.so.0.8.4 per il caricamento e la gestione delle immagini nelle finestre;
  • libSDL_ttf-2.0.so.0.10.1 per la gestione del testo.

Le predette librerie andranno dichiarate ovviamente nelle forme previste dal protocollo Gambas.


Inizializzazione della libreria generale SDL

Prima ancora che si possa utilizzare ogni altra funzione esterna, bisognerà inizializzare la libreria libSDL-1.2.so.0.11.4 mediante la funzione:

int SDL_Init(Uint32 flags)

che in Gambas sarà così dichiarata:

Private Extern SDL_Init(flags As Integer) As Integer

ed in routine potrà essere richiamata come segue:

err = SDL_Init(SDL_INIT_VIDEO)

laddove l'argomento contenuto è un valore numerico intero uguale a 32, che rappresenta il sub-sistema di SDL in particolare da inizializzare (in questo caso il sub-sistema video), e che potrà essere dichiarato come una costante al difuori ovviamente della routine:

 Private Const SDL_INIT_VIDEO As Byte = 32

La funzione ritorna zero se l'inizializzazione ha avuto successo, altrimenti ritorna un valore negativo.


Impostazione della modalità video

Si procederà quindi ad impostare la modalità video, e quindi di visualizzazione effettiva della finestra che si sta andando a creare, specificando la lunghezza, la larghezza ed i bits-per-pixel.
Si utilizzerà la funzione:

SDL_Surface* SDL_SetVideoMode(int width, int height, int bitsperpixel, Uint32 flags)

che in Gambas sarà così dichiarata:

Private Extern SDL_SetVideoMode(width As Integer, height As Integer, bitsperpixel As Integer, flags As Integer) As Pointer

ed in routine potrà essere richiamata - ad esempio - come segue:

 video = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE Or SDL_DOUBLEBUF)

V'è da precisare in via generale riguardo ai parametri previsti da questa funzione che:

  • bits-per-pixel rappresenta i bit desiderati per pixel della modalità video da impostare. Se BitsPerPixel è 0, viene assunta la modalità video uguale a quella corrente. Per la più comune modalità di 4 byte per pixel, è preferibile utilizzare un valore di BitsPerPixel uguale a 32.
  • flags rappresenta una modalità di impostazione video. Per una completa descrizione dei possibili valori che tale argomento può assumere, si rinvia alla specifica documentazione in internet. I valori specifici potranno essere rintracciati nel file: /usr/include/SDL/SDL_video.h.

La funzione restituisce un Puntatore allo specifico framebuffer SDL, con il quale gestire successivamente gli elementi e la vita della finestra.


Caratterizzare la finestra

Così come creata sin ora, la finestra avrà le dimensioni impostate e sarà semplicemente di colore nero con un bordo grigio.
E' possibile apportare alcune modifiche per variare qualche attributo.

Impostare l'intestazione della finestra

Per impostare la critta che apparirà nell'intestazione della finestra, ossia sul lato superiore del suo bordo, si utilizzerà la seguente funzione:

void SDL_WM_SetCaption(const char *title, const char *icon)

laddove i parametri:

  • title è appunto una stringa del testo che sarà mostrato nell'intestazione;
  • icon è il percorso della eventuale icona collegata alla finestra medesima.

Va innanzitutto precisato che questa funzione è contenuta nella libreria libSDL_ttf-2.0.so.0.10.1, e pertanto in Gambas verrà posta dopo la dichiarazione della predetta libreria:

Library "libSDL_ttf-2.0:0.10.1"

e quindi sarà così dichiarata con Extern:

Private Extern SDL_WM_SetCaption(title As String, icon As String)

ed in routine potrà essere così richiamata:

SDL_WM_SetCaption("Intestazione della finestra", "/percorso/della/eventuale/immagine/icona.xxx")

Colorare la finestra

Sarà possibile colorare totalmente o in parte la superficie della finestra mediante la funzione:

int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)

laddove i parametri:

  • *dst è il puntatore al framebuffer ottenuto dalla precedente funzione: "SDL_SetVideoMode";
  • *dstrect è una variabile di tipo Struttura contenente le coordinate e le dimensioni del riquadro colorato all'interno della superficie della finestra;
  • color è un valore numerico intero che rappresenta il colore prescelto.

In Gambas detta funzione sarà così dichiarata con Extern:

Private Extern SDL_FillRect(sdlsurface As Pointer, dstrect As SDL_Rect, color As Integer)

ed in routine potrà essere così richiamata:

SDL_FillRect(video, riquadro, numero_colore)

La Struttura per impostare coordinate e dimensioni del riquadro colorato

Come detto, alla funzione "SDL_FillRect" andrà passata una variabile di tipo Struttura contenente le coordinate e le dimensioni del riquadro colorato che apparirà all'interno della superficie della finestra. Tale Struttura, che definisce un'area quadrangolare, è del tipo SDL_Rect come previsto e specificato nell'API di SDL, sarà dichiarato in Gambas nel modo seguente:

Public Struct SDL_Rect 
  x As Short
  y As Short
  w As Short
  h As Short
End Struct

ovviamente tale Struttura sarà come di consueto gestita attraverso un'apposita variabile che potrà - ad esempio - essere dichiarata (in routine se locale) come segue:

Dim riquadro As New SDL_Rect

Al di sotto della funzione, affinché il risultato sia effettivo, si dovrà utilizzare la seguente funzione:

int SDL_Flip(SDL_Surface* screen)

laddove il parametro screen è il puntatore al framebuffer ottenuto dalla precedente funzione: "SDL_SetVideoMode".
In Gambas detta funzione sarà così dichiarata con Extern:

Private Extern SDL_Flip(sdlsurface As Pointer)

ed in routine potrà essere così richiamata:

SDL_Flip(video)

Da sottolineare che, per poter utilizzare questa funzione, è indispensabile che sia stato impostato il valore SDL_DOUBLEBUF come modalità video nella precedente funzione "SDL_SetVideoMode", che consente di eseguire l'hardware flipping.


Caricare una immagine nella finestra

La finestra può contenere anche un'immagine. Bisognerà innanzitutto utilizzare la funzione:

SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)

laddove i parametri:

  • *file è il percorso del file immagine da caricare;
  • *mode è una delle consuete modalità per aprire un file.

La funzione restituisce un puntatore al flusso di dati del file aperto.
In Gambas detta funzione sarà così dichiarata con Extern:

Private Extern SDL_RWFromFile($file As String, mode As String) As Pointer

ed in routine potrà essere così richiamata:

fl = SDL_RWFromFile("/percorso/della/immagine.bmp", "rb")

laddove la variabile fl sarà stata dichiarata come puntatore.


Quindi si richiamerà a seguire la funzione:

SDL_Surface * SDL_LoadBMP_RW(SDL_RWops *src, int freesrc)

laddove i parametri:

  • *src è il puntatore al file ottenuto dalla precedente funzione "SDL_LoadBMP_RW";
  • freesrc è un valore che se posto ad 1 chiuderà il file automaticamente dopo essere stato caricato.

La funzione ritorna un puntatore, con il quale poter gestire successivamente l'immagine.
In Gambas detta funzione sarà così dichiarata con Extern:

Private Extern SDL_LoadBMP_RW(image As Pointer, freesrc As Integer) As Pointer

ed in routine potrà essere così richiamata:

imago = SDL_LoadBMP_RW(fl, 1)

laddove la variabile imago sarà stata dichiarata come puntatore.


Dopo ciò, per far mostrare effettivamente l'immagine sulla superficie della finestra, si dovrà copiare sostanzialmente la superficie dell'immagine all'interno della finestra medesima, utilizzando la seguente funzione:

int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)

laddove i parametri:

  • *src è il puntatore ottenuto dalla precedente funzione "SDL_LoadBMP_RW";
  • *srcrect è la variabile di tipo Struttura, contenente le sole dimensioni del riquadro dell'immagine, e del tipo SDL_Rect (gia vista per la precedente funzione "SDL_FillRect'"). Se tale parametro è posto a Null, viene copiata l'intera superficie dell'immagine;
  • *dst è il puntatore al framebuffer ottenuto dalla precedente funzione: "SDL_SetVideoMode";
  • *dstrect è la variabile di tipo Struttura, contenente le sole coordinate del riquadro dell'immagine, e del tipo SDL_Rect. Se tale parametro è posto a Null, allora posizione di destinazione è: 0, 0 (ossia nell'angolo sinistro in alto).

Da sottolineare che questa funzione è contenuta nella libreria libSDL_image-1.2.so.0.8.4.
In Gambas detta funzione sarà così dichiarata con Extern:

Private Extern SDL_UpperBlit(image As Pointer, srcrect As Pointer, dst As Pointer, dstrect As SDL_Rect) As Integer In "libSDL_image-1.2:0.8.4"

ed in routine potrà essere - ad esempio - così richiamata:

SDL_UpperBlit(imago, Null, video, Null)

Aggiornare le modifiche apportate alla superficie della finestra

E' buona norma assicurarsi che ogni cambiamento apportato alla superficie della finestra (come appunto ad esempio il caricamento di un'immagine) sia consolidato con la funzione:

void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h)

laddove i parametri:

  • *screen è il puntatore al framebuffer ottenuto dalla precedente funzione: "SDL_SetVideoMode";
  • Sint32 x, Sint32 y, Sint32 w, Sint32 h sono le coordinate e le dimensioni dell'area che si va ad aggiornare.

Va sottolineato che se tali quattro ultimi parametri sono posti tutti a zero, la funzione aggiornerà l'intera superficie della finestra.
In Gambas detta funzione sarà così dichiarata con Extern:

Private Extern SDL_UpdateRect(sdlsurface As Pointer, x As Integer, y As Integer, w As Integer, h As Integer)

ed in routine potrà essere - ad esempio - così richiamata:

SDL_UpdateRect(video, 0, 0, valore W, valore H)


Ottenere alcune informazioni sull'immagine

E' possibile ottenere alcune informazioni sull'imagine caricata andando a leggere all'interno del puntatore ottenuto dalla funzione "SDL_LoadBMP_RW".
Ad esempio, si potranno leggere/ottenere i valori in pixel delle dimensioni dell'immagine attraverso i Memory-Stream, cose segue:

Dim imago As Pointer
Dim ist As Stream
Dim iW, iH As Integer 

ist = Memory imago For Read
 Seek #ist1, 16   ' Si legge al 17° e poi al 21° byte
 Read #ist1, iW
  Print iW
 Read #ist1, iH
  Print iH



Riferimenti


Pagina in costruzione !