/* For the sake of brevity, the example is a single task. No Layer ** locking is done. Also note that the routine myLabelLayer() is used ** to redraw a given layer. It is called only when a layer needs ** refreshing. ** ** Layers.c ** ** SAS/C 5.10a ** lc -b1 -cfist -v -y layers ** blink FROM LIB:c.o layers.o TO layers LIB LIB:lc.lib LIB:amiga.lib */ /* Force use of new variable names to help prevent errors */ #define INTUI_V36_NAMES_ONLY #include <exec/types.h> #include <graphics/gfxbase.h> #include <graphics/layers.h> #include <graphics/displayinfo.h> #include <clib/exec_protos.h> #include <clib/dos_protos.h> #include <clib/graphics_protos.h> #include <clib/layers_protos.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef LATTICE int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */ int chkabort(void) { return(0); } /* really */ #endif #define L_DELAY (100) #define S_DELAY (50) #define DUMMY (0L) #define RED_PEN (1) #define GREEN_PEN (2) #define BLUE_PEN (3) #define SCREEN_D (2) #define SCREEN_W (320) #define SCREEN_H (200) /* the starting size of example layers, offsets are used for placement */ #define W_H (50) #define W_T (5) #define W_B ((W_T+W_H)-1) #define W_W (80) #define W_L ((SCREEN_W/2) - (W_W/2)) #define W_R ((W_L+W_W)-1) /* size of the superbitmap */ #define SUPER_H SCREEN_H #define SUPER_W SCREEN_W /* starting size of the message layer */ #define M_H (10) #define M_T (SCREEN_H-M_H) #define M_B ((M_T+M_H)-1) #define M_W (SCREEN_W) #define M_L (0) #define M_R ((M_L+M_W)-1) struct GfxBase *GfxBase; struct Library *LayersBase; /* global constant data for initializing the layers */ LONG theLayerFlags[3] = { LAYERSUPER, LAYERSMART, LAYERSIMPLE }; UWORD colortable[] = { 0x000, 0xf44, 0x4f4, 0x44f }; /* ** Clear the layer then draw in a text string. */ VOID myLabelLayer(struct Layer *layer, LONG color, UBYTE *string) { /* fill layer with color */ SetRast(layer->rp, color); /* set up for writing text into layer */ SetDrMd(layer->rp,JAM1); SetAPen(layer->rp,0); Move(layer->rp, 5, 7); /* write into layer */ Text(layer->rp, string, strlen(string)); } /* ** write a message into a layer with a delay. */ VOID pMessage(struct Layer *layer, UBYTE *string) { Delay(S_DELAY); myLabelLayer(layer, GREEN_PEN, string); } /* ** write an error message into a layer with a delay. */ VOID error(struct Layer *layer, UBYTE *string) { myLabelLayer(layer, RED_PEN, string); Delay(L_DELAY); } /* ** do some layers manipulations to demonstrate their abilities. */ VOID doLayers(struct Layer *msgLayer, struct Layer *layer_array[]) { WORD ktr; WORD ktr_2; pMessage(msgLayer, "Label all Layers"); myLabelLayer(layer_array[0], RED_PEN, "Super"); myLabelLayer(layer_array[1], GREEN_PEN, "Smart"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); pMessage(msgLayer, "MoveLayer 1 InFrontOf 0"); if (!MoveLayerInFrontOf(layer_array[1], layer_array[0])) error(msgLayer, "MoveLayerInFrontOf() failed."); pMessage(msgLayer, "MoveLayer 2 InFrontOf 1"); if (!MoveLayerInFrontOf(layer_array[2], layer_array[1])) error(msgLayer, "MoveLayerInFrontOf() failed."); pMessage(msgLayer, "Refresh Simple Refresh Layer"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); pMessage(msgLayer, "Incrementally MoveLayers..."); for(ktr = 0; ktr < 30; ktr++) { if (!MoveLayer(DUMMY, layer_array[1], -1, 0)) error(msgLayer, "MoveLayer() failed."); if (!MoveLayer(DUMMY, layer_array[2], -2, 0)) error(msgLayer, "MoveLayer() failed."); } pMessage(msgLayer, "Refresh Simple Refresh Layer"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); pMessage(msgLayer, "make Layer 0 the UpfrontLayer"); if (!UpfrontLayer(DUMMY, layer_array[0])) error(msgLayer, "UpfrontLayer() failed."); pMessage(msgLayer, "make Layer 2 the BehindLayer"); if (!BehindLayer(DUMMY, layer_array[2])) error(msgLayer, "BehindLayer() failed."); pMessage(msgLayer, "Incrementally MoveLayers again..."); for(ktr = 0; ktr < 30; ktr++) { if (!MoveLayer(DUMMY, layer_array[1], 0, 1)) error(msgLayer, "MoveLayer() failed."); if (!MoveLayer(DUMMY, layer_array[2], 0, 2)) error(msgLayer, "MoveLayer() failed."); } pMessage(msgLayer, "Refresh Simple Refresh Layer"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); pMessage(msgLayer, "Big MoveLayer"); for(ktr = 0; ktr < 3; ktr++) { if (!MoveLayer(DUMMY, layer_array[ktr], -layer_array[ktr]->bounds.MinX, 0)) error(msgLayer, "MoveLayer() failed."); } pMessage(msgLayer, "Incrementally increase size"); for(ktr = 0; ktr < 5; ktr++) { for(ktr_2 = 0; ktr_2 < 3; ktr_2++) { if (!SizeLayer(DUMMY, layer_array[ktr_2], 1, 1)) error(msgLayer, "SizeLayer() failed."); } } pMessage(msgLayer, "Refresh Smart Refresh Layer"); myLabelLayer(layer_array[1], GREEN_PEN, "Smart"); pMessage(msgLayer, "Refresh Simple Refresh Layer"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); pMessage(msgLayer, "Big SizeLayer"); for(ktr = 0; ktr < 3; ktr++) { if (!SizeLayer(DUMMY,layer_array[ktr], SCREEN_W-(layer_array[ktr]->bounds.MaxX)-1,0)) error(msgLayer, "SizeLayer() failed."); } pMessage(msgLayer, "Refresh Smart Refresh Layer"); myLabelLayer(layer_array[1], GREEN_PEN, "Smart"); pMessage(msgLayer, "Refresh Simple Refresh Layer"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); pMessage(msgLayer, "ScrollLayer down"); for(ktr = 0; ktr < 30; ktr++) { for(ktr_2 = 0; ktr_2 < 3; ktr_2++) { ScrollLayer(DUMMY, layer_array[ktr_2], 0, -1); } } pMessage(msgLayer, "Refresh Smart Refresh Layer"); myLabelLayer(layer_array[1], GREEN_PEN, "Smart"); pMessage(msgLayer, "Refresh Simple Refresh Layer"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); pMessage(msgLayer, "ScrollLayer up"); for(ktr = 0; ktr < 30; ktr++) { for(ktr_2 = 0; ktr_2 < 3; ktr_2++) { ScrollLayer(DUMMY, layer_array[ktr_2], 0, 1); } } pMessage(msgLayer, "Refresh Smart Refresh Layer"); myLabelLayer(layer_array[1], GREEN_PEN, "Smart"); pMessage(msgLayer, "Refresh Simple Refresh Layer"); myLabelLayer(layer_array[2], BLUE_PEN, "Simple"); Delay(L_DELAY); } /* ** delete the layer array created by allocLayers(). */ VOID disposeLayers(struct Layer *msgLayer, struct Layer *layer_array[]) { WORD ktr; for (ktr = 0; ktr < 3; ktr++) { if (layer_array[ktr] != NULL) { if (!DeleteLayer(DUMMY, layer_array[ktr])) error(msgLayer, "Error deleting layer"); } } } /* ** Create some hard-coded layers. The first must be super-bitmap, with ** the bitmap passed as an argument. The others must not be super-bitmap. ** The pointers to the created layers are returned in layer_array. ** ** Return FALSE on failure. On a FALSE return, the layers are ** properly cleaned up. */ BOOL allocLayers(struct Layer *msgLayer, struct Layer *layer_array[], struct BitMap *super_bitmap, struct Layer_Info *theLayerInfo, struct BitMap *theBitMap) { WORD ktr; BOOL create_layer_ok = TRUE; for (ktr = 0; (ktr < 3) && (create_layer_ok); ktr++) { pMessage(msgLayer, "Create BehindLayer"); if (ktr == 0) { if ((layer_array[ktr] = CreateBehindLayer(theLayerInfo, theBitMap, W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30), theLayerFlags[ktr], super_bitmap)) == NULL) create_layer_ok = FALSE; } else { if ((layer_array[ktr] = CreateBehindLayer(theLayerInfo, theBitMap, W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30), theLayerFlags[ktr], NULL)) == NULL) create_layer_ok = FALSE; } if (create_layer_ok) { pMessage(msgLayer, "Fill the RastPort"); SetRast(layer_array[ktr]->rp, ktr + 1); } } if (!create_layer_ok) disposeLayers(msgLayer, layer_array); return(create_layer_ok); } /* ** Free the bitmap and all bitplanes created by allocBitMap(). */ VOID disposeBitMap(struct BitMap *bitmap, LONG depth, LONG width, LONG height) { WORD ktr; if (NULL != bitmap) { for (ktr = 0; ktr < depth; ktr++) { if (NULL != bitmap->Planes[ktr]) FreeRaster(bitmap->Planes[ktr], width, height); } FreeMem(bitmap, sizeof(*bitmap)); } } /* ** Allocate and initialize a bitmap structure. */ struct BitMap *allocBitMap(LONG depth, LONG width, LONG height) { WORD ktr; BOOL bit_map_failed = FALSE; struct BitMap *bitmap = NULL; if (NULL != (bitmap = AllocMem(sizeof(*bitmap),NULL))) { InitBitMap(bitmap,depth,width,height); for (ktr = 0; ktr < depth; ktr++) { if (NULL == (bitmap->Planes[ktr] = (PLANEPTR)AllocRaster(width,height))) bit_map_failed = TRUE; else BltClear(bitmap->Planes[ktr], RASSIZE(width,height), 1); } if (bit_map_failed) { disposeBitMap(bitmap,depth,width,height); bitmap = NULL; } } return(bitmap); } /* ** Set up to run the layers example, doLayers(). Clean up when done. */ VOID startLayers(struct Layer_Info *theLayerInfo, struct BitMap *theBitMap) { struct Layer *msgLayer; struct BitMap *theSuperBitMap; struct Layer *theLayers[3] = { NULL, NULL, NULL, }; if (NULL != (msgLayer = CreateUpfrontLayer(theLayerInfo, theBitMap, M_L, M_T, M_R, M_B, LAYERSMART, NULL))) { pMessage(msgLayer, "Setting up Layers"); if (NULL != (theSuperBitMap = allocBitMap(SCREEN_D, SUPER_W, SUPER_H))) { if (allocLayers(msgLayer, theLayers, theSuperBitMap, theLayerInfo, theBitMap)) { doLayers(msgLayer, theLayers); disposeLayers(msgLayer, theLayers); } disposeBitMap(theSuperBitMap, SCREEN_D, SUPER_W, SUPER_H); } if (!DeleteLayer(DUMMY, msgLayer)) error(msgLayer, "Error deleting layer"); } } /* ** Set up a low-level graphics display for layers to work on. Layers ** should not be built directly on Intuition screens, use a low-level ** graphics view. If you need mouse or other events for the layers ** display, you have to get them directly from the input device. The ** only supported method of using layers library calls with Intuition ** (other than the InstallClipRegion() call) is through Intuition windows. ** ** See graphics primitives chapter for details on creating and using the ** low-level graphics calls. */ VOID runNewView(VOID) { struct View theView; struct View *oldview; struct ViewPort theViewPort; struct RasInfo theRasInfo; struct ColorMap *theColorMap; struct Layer_Info *theLayerInfo; struct BitMap *theBitMap; UWORD *colorpalette; WORD ktr; /* save current view, to be restored when done */ if (NULL != (oldview = GfxBase->ActiView)) { /* get a LayerInfo structure */ if (NULL != (theLayerInfo = NewLayerInfo())) { if (NULL != (theColorMap = GetColorMap(4))) { colorpalette = (UWORD *)theColorMap->ColorTable; for(ktr = 0; ktr < 4; ktr++) *colorpalette++ = colortable[ktr]; if (NULL != (theBitMap = allocBitMap(SCREEN_D, SCREEN_W, SCREEN_H))) { InitView(&theView); InitVPort(&theViewPort); theView.ViewPort = &theViewPort; theViewPort.DWidth = SCREEN_W; theViewPort.DHeight = SCREEN_H; theViewPort.RasInfo = &theRasInfo; theViewPort.ColorMap = theColorMap; theRasInfo.BitMap = theBitMap; theRasInfo.RxOffset = 0; theRasInfo.RyOffset = 0; theRasInfo.Next = NULL; MakeVPort(&theView, &theViewPort); MrgCop(&theView); LoadView(&theView); WaitTOF(); startLayers(theLayerInfo, theBitMap); /* put back the old view, wait for it to become ** active before freeing any of our display */ LoadView(oldview); WaitTOF(); /* free dynamically created structures */ FreeVPortCopLists(&theViewPort); FreeCprList(theView.LOFCprList); disposeBitMap(theBitMap, SCREEN_D, SCREEN_W, SCREEN_H); } FreeColorMap(theColorMap); /* free the color map */ } DisposeLayerInfo(theLayerInfo); } } } /* ** Open the libraries used by the example. Clean up when done. */ VOID main(int argc, char **argv) { if (NULL != (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",33L))) { if (NULL != (LayersBase = OpenLibrary("layers.library",33L))) { runNewView(); CloseLibrary((struct Library *)LayersBase); } CloseLibrary((struct Library *)GfxBase); } }