[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

/* 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);
    }
}


[Back to Amiga Developer Docs]