Corso di AmigaOS

Torna all'elenco delle lezioniPer dubbi, consigli o richieste, potete mandare un'e-mail ad Andrea Carolfi.
Ringraziamo Amiga Transactor Mailing List per questo tangibile contributo!


La Graphics.Library (Sedicesima lezione)

Continuiamo l'excursus sulle funzioni della graphics.library.
Nella lezione precedente erano state introdotte alcune funzioni che permettono la creazione di grafica grezza tramite output di testo grafico, tracciamento di linee, cerchi, ellissi e rettangoli pieni.
In questa lezione vediamo le seguenti funzioni.


Operazioni sulle bitmap

LONG BltBitMap( struct BitMap *srcBitMap, long xSrc, long ySrc,
                struct BitMap *destBitMap, long xDest, long yDest,
                long xSize, long ySize, unsigned long minterm,
                unsigned long mask, PLANEPTR tempA );

Questa funzione copia un'area rettangolare di dimensioni xSize ySize dalla posizione xSrc ySrc (angolo in alto a sinistra) dalla bitmap srcBitMap alla bitmap destBitMap alla posizione xDest yDest. La bitmap di destinazione può essere la stessa.

Il campo minterm, determina che operazione logica compiere tra ogni pixel ricopiato e quelli che verranno sovrascritti per deteminare il risultato finale.
Valori tipici sono 0xC0 (ricopia sovrascrivendo), 0x30 (inverte la sorgente prima di copiarla), 0x50 (ignora la sorgente ed inverte la destinazione).
Il campo mask, determina quali piani di bit devono essere coinvolti nella operazione (non dimentichiamoci che il display grafico originale è planare).
Di solito si usa 0xFF che vuol dire tutti quanti. Ma è possibile dis/abilitarli uno a uno.
Infine, il campo TempA, contiene l'eventuale puntatore ad un'area di memoria sufficente a mantenere una linea della bitmap sorgente. Questo serve per gestire l'eventuale fuoriuscita, a destra od a sinistra, dell'area ricopiata nella bitmap destinazione. Visto che la routine gestisce autonomamente l'allocazione di questa eventuale memoria aggiuntiva, di solito si lascia questo campo a NULL.

void BltTemplate( PLANEPTR source, long xSrc, long srcMod, struct RastPort
                  *destRP, long xDest, long yDest, long xSize, long ySize );

Questa routine, disegna l'immagine presente nel template source nella rastport destRP, utilizzando colore e modo di disegno attuali alle posizioni specificate.
xSrc, determina l'offset della maschera, può variare tra 0 e 15. srcMod, specifica il numero di bytes per riga nella maschera.

void BltBitMapRastPort( struct BitMap *srcBitMap, long xSrc, long ySrc,
                        struct RastPort *destRP, long xDest, long yDest,
                        long xSize, long ySize, unsigned long minterm );

Praticamente identica alla BltBitMap, compie la stessa operazione salvo che non necessita del campo mask (viene determinata dalla rastport) e TempA.
Ovviamente, essendo finalizzata a copiare una bitmap in una rastport è generalmente preferibile, in questi casi, alla BltBitMap.

void BitMapScale( struct BitScaleArgs *bitScaleArgs );

Questa 'simpatica' funzione, permette di ridimensionare (ovvero scalare) una bitmap.
Inizializzando ai valori opportuni la struttura BitScaleArgs è possibile diminuire o aumentare le dimensioni della nostra immagine presente in una bitmap. Vediamo come.

struct BitScaleArgs {
      UWORD   bsa_SrcX, bsa_SrcY;        /* source origin */
      UWORD   bsa_SrcWidth, bsa_SrcHeight;  /* source size */
      UWORD   bsa_XSrcFactor, bsa_YSrcFactor;  /* scale factor denominators */
      UWORD   bsa_DestX, bsa_DestY;      /* destination origin */
      UWORD   bsa_DestWidth, bsa_DestHeight;   /* destination size result */
      UWORD   bsa_XDestFactor, bsa_YDestFactor;   /* scale factor numerators */
      struct BitMap *bsa_SrcBitMap;      /* source BitMap */
      struct BitMap *bsa_DestBitMap;     /* destination BitMap */
      ULONG   bsa_Flags;           /* reserved.  Must be zero! */
      UWORD   bsa_XDDA, bsa_YDDA;        /* reserved */
      LONG    bsa_Reserved1;
      LONG    bsa_Reserved2;
};

I campi bsa_SrcBitMap e bsa_DestBitMap indicano rispettivamente la bitmap sorgente e quella destinazione.
I primi quattro campi, servono per definire l'area coinvolta nell'operazione. I parametri bsa_XSrcFactor, bsa_XDestFactor, bsa_YSrcFactor e bsa_YDestFactor servono per determinare le proporzioni della bitmap di destinazione.
Per esempio, se bsa_XSrcFactor = 1, bsa_XDestFactor = 2, bsa_YSrcFactor = 2 bsa_YDestFactor = 1, l'immagine sarà larga il doppio e alta la metà.
bsa_DestX e bsa_DestY indicano la posizione nella quale blittare l'immagine.
bsa_DestWidth e bsa_DestHeight vengono impostati dalla routine.

void ScrollRaster( struct RastPort *rp, long dx, long dy, long xMin,
                   long yMin, long xMax, long yMax );

Opera uno shiftamento di un'area rettangolare specificata da (xMin,yMin) e (xMax,YMax) di (dx,dy) pixel verso (0,0). La parte precedentemente occupata dai pixel spostati viene riempita con il colore di sfondo.

ULONG GetBitMapAttr( struct BitMap *bm, unsigned long attrnum );

Questa routine è stata introdotta a partire dalla versione 3.0 del SO per garantire future compatibilità con display grafici diversi dal chipset nativo.
Invece di leggere direttamente i valori dei campi della struttura bitmap che ci interessa, si deve usare questa procedura.
Attualmente i parametri che possono essere ottenuti sono:
BMA_HEIGHT, BMA_WIDTH, BMA_DEPTH, e BMA_FLAGS. I primi tre sono di ovvia intuizione, il quarto può essere una combinazione dei flag:
BMF_INTERLEAVED, BMF_DISPLAYABLE e BMF_STANDARD. Che indicano se una bitmap è interleaved (ovvero i vari piani di bit sono allocati in un unico blocco di memoria chip, se è visualizzabile (ovvero se rispetta particolari allineamenti e restrizioni per essere visualizzata) e se la bitmap è rappresentata da dati planari in memoria chip. Quindi, se questo flag non è presente, la bitmap non è allocata in memoria chip e con molta probabilità è in formato chunky.


Tracciamento linee e riempimento aree

struct TmpRas *InitTmpRas( struct TmpRas *tmpRas, PLANEPTR buffer,
                           long size );

Permette di collegare un'area di memoria chip allocata ad una struttura TmpRas di una RastPort in modo che possa essere utilizzata da quelle routine che necessitano di un'area di memoria grafica temporanea per effettuare operazioni intermedie (ad esempio Flood).

void InitArea( struct AreaInfo *areaInfo, APTR vectorBuffer,
               long maxVectors );

Necessaria per inizializzare un area di memoria (anche non grafica) per memorizzare informazioni temporanee necessarie ad alcune routine grafiche come AreaEllipse e AreaMove.

LONG AreaEllipse( struct RastPort *rp, long xCenter, long yCenter, long a,
                  long b );
LONG AreaMove( struct RastPort *rp, long x, long y );
LONG AreaDraw( struct RastPort *rp, long x, long y );
void PolyDraw( struct RastPort *rp, long count, WORD *polyTable );

Queste routine, una volta inizializzata l'AreaInfo con la InitArea, permettono di tracciare ellissi, linee e poligoni che poi saranno riempiti. La funzione PolyDraw, necessita di un array di coordinate che indicano i vertici del poligono. 'count' indica il numero di coppie presenti nell'array.

LONG AreaEnd( struct RastPort *rp );

Questa routine deve essere chiamata dopo le precedenti per completare le operazioni di tracciamento.

void BltPattern( struct RastPort *rp, PLANEPTR mask, long xMin, long yMin,
                 long xMax, long yMax, unsigned long maskBPR );


BOOL Flood( struct RastPort *rp, unsigned long mode, long x, long y );

Questa funzione, una volta inizializzata la struttua TmpRas, può essere utilizzata per effettuare dei riempimenti di aree circoscritte. La documentazione, afferma che per poterla utilizzare, l'area di memoria puntata dalla struttura TmpRas della RastPort deve essere grande quando la RastPort. Quindi se abbiamo una RastPort di 640x480 pixel, dobbiamo allocare un piano di bit di 640x480 pixel.


Operazioni su colori e tavolozza

ULONG ObtainPen( struct ColorMap *cm, unsigned long n, unsigned long r,
                 unsigned long g, unsigned long b, long f );

Data una colormap, richiede al sistema di allocare una penna con un determinato colore (r,g,b) possibilmente alla locazione n o qualsiasi se n = -1. La penna può essere allocata in maniera esclusiva o condivisa. Questo viene specificato dal valore del flag f che può essere PEN_ECLUSIVE e/o PEN_NO_SETCOLOR che indica al sistema di non modificare i valori rgb della penna selezionata.

LONG ObtainBestPenA( struct ColorMap *cm, unsigned long r, unsigned long g,
        unsigned long b, struct TagItem *tags );
LONG ObtainBestPen( struct ColorMap *cm, unsigned long r, unsigned long g,
        unsigned long b, unsigned long tag1Type, ... );

In un'ambiente condiviso, tipo lo schermo del Workbench, è preferibile utilizzare questa procedura piuttosto che la ObtainPen. Questo perchè questa routine cerca di allocare una penna che più si avvicina come valori rgb a quelli richiesti e generalmente (a meno di non averlo esplicitamente richiesto con il flag OBP_FailIfBad) non fallisce se non trova una penna che soddisfi i requisiti richiesti. E' quindi utile per un programma che visualizza un immagine o per altri scopi in cui ci si può accontentare di un'approssimazione e non abbiamo bisogno di una palette perfetta.
E' possibile specificare il determinato grado di precisione richiesta tramite il tag OBP_Precision che può essere (dal peggiore al migliore): PRECISION_GUI, PRECISION_ICON, PRECISION_IMAGE e PRECISION_EXACT. Il predefinito è PRECISION_IMAGE.

void ReleasePen( struct ColorMap *cm, unsigned long n );

Una volta che abbiamo ottenuto una penna tramite ObtainPen o ObtainBestPen/A quando non ci servirà più dovremo liberarla utilizzando questa funzione.

void LoadRGB32( struct ViewPort *vp, ULONG *table );

Modifica la tavolozza dei colori di una viewport.
La tavolozza viene specificata da un array di long senza segno inzializzato in questo modo:

  • 1 word con il numero di colori da modificare
  • 1 word con il primo colore da modificare
  • 3 long che rappresentano una tripletta rgb giustificata a sinistra.

La lista è terminata dal valore 0.
Per esempio:

ULONG table[] = {1L << 16 + 0,0xFFFFFFFF,0,0,0};
imposta il solo colore 0 a rosso.

ULONG table[] = {256L << 16 + 0,r1,g1,b1,r2,g2,b2,...,0};

imposta una palette di 256 colori.


void SetRGB32( struct ViewPort *vp, unsigned long n, unsigned long r,
        unsigned long g, unsigned long b );

Simile alla LoadRGB32 solo che modifica un unico colore. Nella documentazione della graphics.library, comunque c'è scritto che anche per impostare un solo colore è più veloce la LoadRGB32.

void GetRGB32( struct ColorMap *cm, unsigned long firstcolor,
        unsigned long ncolors, ULONG *table );

Data una colormap, interroga ncolors a partire dal firstcolor e valorizza la tabella table con i valori RGB di ogni colore.
Utile ad esempio per salvarsi una configurazione modificata dall'utente.

ULONG GetAPen( struct RastPort *rp );
ULONG GetBPen( struct RastPort *rp );
ULONG GetDrMd( struct RastPort *rp );
ULONG GetOutlinePen( struct RastPort *rp );

Ricordate le SetXXX della puntata precedente? :-) Queste compiono l'operazione inversa, invece di impostare il valore, ritornano quello attuale.

void SetABPenDrMd( struct RastPort *rp, unsigned long apen,
        unsigned long bpen, unsigned long drawmode );

Discorso simile per questa procedura, che in una volta sola, svolge il compito di SetAPen, SetBPen e SetDrMd.

Listato di questa lezione

Lezione precedente Indice delle lezioni Lezione successiva
Copyright AMiWoRLD Ph0ton