>
In questa lezione cominceremo ad avvicinarci ad un'altra importante libreria del sistema operativo di Amiga: la graphics.library. Questa enorme libreria (conta ben 179 funzioni pubbliche) si incarica di interfacciarsi con l'hardware grafico di Amiga e permette di compiere un certo numero di operazioni grafiche.
Purtroppo, quello che manca a questa libreria è un completo supporto RTG per l'hardware che fortunatamente è possibile aggiungere tramite CGX o Picasso96 sostituendo alcune funzioni di questa libreria per permettergli di operare anche senza il chipset (vedi DraCo).
Comunque, seguendo alcuni accorgimenti è possibile, avvalendosi del display database, far girare la propria applicazione grafica sia su schermo OCS/ECS/AGA che su scheda grafica.
Prima di vedere le primitive grafiche di questa lezione, è necessario specificare che praticamente tutte le funzioni grafiche necessitano di una bitmap associata ad una rastport.
Vediamo dunque queste strutture.
BitMap e RastPort
-----------------
typedef UBYTE *PLANEPTR;
struct BitMap
{
UWORD BytesPerRow;
UWORD Rows;
UBYTE Flags;
UBYTE Depth;
UWORD pad;
PLANEPTR Planes[8];
};
struct RastPort
{
struct Layer *Layer;
struct BitMap *BitMap;
UWORD *AreaPtrn; /* ptr to areafill pattern */
struct TmpRas *TmpRas;
struct AreaInfo *AreaInfo;
struct GelsInfo *GelsInfo;
UBYTE Mask; /* write mask for this raster */
BYTE FgPen; /* foreground pen for this raster */
BYTE BgPen; /* background pen */
BYTE AOlPen; /* areafill outline pen */
BYTE DrawMode; /* drawing mode for fill, lines, and text */
BYTE AreaPtSz; /* 2^n words for areafill pattern */
BYTE linpatcnt; /* current line drawing pattern preshift */
BYTE dummy;
UWORD Flags; /* miscellaneous control bits */
UWORD LinePtrn; /* 16 bits for textured lines */
WORD cp_x, cp_y; /* current pen position */
UBYTE minterms[8];
WORD PenWidth;
WORD PenHeight;
struct TextFont *Font; /* current font address */
UBYTE AlgoStyle; /* the algorithmically generated style */
UBYTE TxFlags; /* text specific flags */
UWORD TxHeight; /* text height */
UWORD TxWidth; /* text nominal width */
UWORD TxBaseline; /* text baseline */
WORD TxSpacing; /* text spacing (per character) */
APTR *RP_User;
ULONG longreserved[2];
#ifndef GFX_RASTPORT_1_2
UWORD wordreserved[7]; /* used to be a node */
UBYTE reserved[8]; /* for future use */
#endif
};
La bitmap è proprio dove le operazioni grafiche andranno a scrivere o leggere (a seconda della funzione chiamata). La rastport contiene informazioni sullo stato attuale di colore di sfondo, colore di primo piano, posizione del cursore grafico, carattere utilizzato e via di seguito.
Abbiamo una rastport per ogni finestra e una per ogni schermo, ma non è strettamente necessario. È possibile avere una bitmap e una rastport "nascoste" su cui lavorare internamente per poi ricopiare sulla finestra (double buffering).
Vediamo quindi come creare una bitmap. Una volta, era necessario allocare i vari piani necessari, inzializzarli, allocare la bitmap, inizializzarla, collegare i piani alla bitmap, e poi collegare la bitmap alla rastport. A partire dal 3.0 viene messa a disposizione la funzione AllocBitMap() che facilita l'operazione; vediamo:
struct RastPort rp;
struct BitMap *bm;
InitRastPort(&rp);
if((bm = AllocBitMap(320,200,8,BMF_CLEAR,NULL)))
{
rp.BitMap = bm;
...
FreeBitMap(bm);
}
Questo stralcio di codice, inizializza una rastport ai valori predefiniti, alloca una bitmap ad otto piani (256 colori) di dimensioni 320x200 inizializzandola al colore 0 e collegandola alla rastport precedentemente valorizzata.
Successivamente la bitmap viene deallocata.
Il campo NULL della funzione é un puntatore ad una bitmap "amica" (in questo caso nessuna) che può essere richiesta per allocare la bitmap in modo da rendere le blittate dalla bitmap a quella amica più efficenti.
Primitive grafiche
------------------
Vediamo adesso alcune primitive grafiche:
void DrawEllipse( struct RastPort *rp, long xCenter, long yCenter, long a,
long b );
Disegna sulla RastPort rp, un ellisse di centro (xCenter,yCenter) e raggi
a b. Se vogliamo disegnare un cerchio non bisogna far altro che specificare
lo stesso valore per entrambi i raggi.
#§codestart
void SetRast( struct RastPort *rp, unsigned long pen );
Ripulisce con il colore pen la RastPort rp cancellando quindi tutto il suo contenuto.
void Move( struct RastPort *rp, long x, long y );
Sposta il cursore grafico alle coordinate x,y.
void Draw( struct RastPort *rp, long x, long y );
Traccia una riga dalla posizione attuale del cursore grafico fino alle coordinate x e y specificate.
void RectFill( struct RastPort *rp, long xMin, long yMin, long xMax, long yMax );
Disegna un rettangolo pieno con angolo superiore sinistro xMin yMin e angolo inferiore destro xMax yMax.
!!! ATTENZIONE !!!
if(xMax < xMin || yMax < yMin) crashsystem();
In parole :-) : le coordinate xMax e yMax devono essere maggiori o uguali a xMin e yMin, altrimenti si pianta tutto il sistema.
ULONG ReadPixel( struct RastPort *rp, long x, long y );
Restituisce il valore del colore usato dal pixel posizionato alle coordinate (x,y) specificate.
LONG WritePixel( struct RastPort *rp, long x, long y );
Cambia il colore del pixel posizionato alle coordinate (x,y), in accordo con quello specificato tramite SetAPen. Ritorna 0 in caso di successo o -1 nel caso in cui il punto sia fuori dalla RastPort.
void SetAPen( struct RastPort *rp, unsigned long pen );
Imposta il valore della penna di primo piano al valore pen.
void SetBPen( struct RastPort *rp, unsigned long pen );
Imposta il valore della penna di sfondo al valore pen.
void SetOPen( struct RastPort *rp, unsigned long pen );
Imposta il valore della penna di contorno (utilizzata in alcune funzioni) al valore pen.
void SetDrMd( struct RastPort *rp, unsigned long drawMode );
Imposta il valore del modo di disegno al valore drawMode.
I modi possibili sono:
#define JAM1 0 /* jam 1 color into raster */
#define JAM2 1 /* jam 2 colors into raster */
#define COMPLEMENT 2 /* XOR bits into raster */
#define INVERSVID 4 /* inverse video for drawing modes */
WORD TextLength( struct RastPort *rp, STRPTR string, unsigned long count );
Calcola l'occupazione in pixel sulla RastPort rp, dei primi count caratteri della stringa string.
LONG Text( struct RastPort *rp, STRPTR string, unsigned long count );
Visualizza alla posizione attuale del cursore grafico count caratteri della stringa string utilizzando il carattere selezionato.
LONG SetFont( struct RastPort *rp, struct TextFont *textFont );
Modifica il carattere da usare con la RastPort rp con il font precedentemente aperto textFont.
struct TextFont *OpenFont( struct TextAttr *textAttr );
Carica il carattere descritto dalla struttura textAttr e lo restituisce.
La struttura TextAttr è così definita:
struct TextAttr {
STRPTR ta_Name; /* name of the font */
UWORD ta_YSize; /* height of the font */
UBYTE ta_Style; /* intrinsic font style */
UBYTE ta_Flags; /* font preferences and flags */
};
Un esempio di inizializzazione è: struct TextAttr MyFont = {"helvetica.font",15,FS_NORMAL,FPF_DISKFONT};
I flags sono definiti in include:graphics/text.h
void CloseFont( struct TextFont *textFont );
Chiude il font precedentemente aperto tramite OpenFont o OpenDiskFont (della. diskfont.library che vedremo in seguito).
ULONG AskSoftStyle( struct RastPort *rp );
Restituisce gli stili del carattere usato nella RastPort rp che non sono proprietà del carattere stesso ma calcolati via software.
Questi sono i bits validi per impostare la maschera enable per la funzione
SetSoftStyle.
ULONG SetSoftStyle( struct RastPort *rp, unsigned long style, unsigned long enable);
Richiede uno stile software per il carattere usato dalla RastPort rp (grassetto italico, sottolineato).
I possibili stili sono:
#define FS_NORMAL 0 /* normal text (no style bits set) */
#define FSF_UNDERLINED 0x01 /* underlined (under baseline) */
#define FSF_BOLD 0x02 /* bold face text (ORed w/ shifted) */
#define FSF_ITALIC 0x04 /* italic (slanted 1:2 right) */
#define FSF_EXTENDED 0x08 /* extended face (wider than normal) */
#define FSF_COLORFONT 0x40 /* this uses ColorTextFont structure */
#define FSF_TAGGED 0x80 /* the TextAttr is really an TTextAttr, */
Anche se onestamente non ho mai usato gli ultimi tre.
Bene, per questa lezione abbiamo finito, ci risentiamo alla prossima!