{ Example program to manipulate three layers on the screen.           }
{ For details of the compiler and linker command lines see Appendix D }

PROGRAM layers( output );

INCLUDE 'exec/types.h';
INCLUDE 'graphics/gfx.h';
INCLUDE 'graphics/copper.h';
INCLUDE 'graphics/view.h';
INCLUDE 'graphics/gels.h';
INCLUDE 'graphics/clip.h';
INCLUDE 'graphics/gfxbase.h';
INCLUDE 'graphics/layers.h';

CONST
 DEPTH   = 2;    { Depth of 2 means 3 planes }
 WIDTH   = 320;  { Screen width }
 HEIGHT  = 200;  { Screen height }
 RASSIZE = 8000; { Raster size in bytes }
 NLAYERS = 3;    { There are three layers }

TYPE
 colourtablePtrType = ^colourtableType;
 colourtableType = PACKED ARRAY[0..3] OF WORD; 

 paletteType = PACKED RECORD
                CASE BOOLEAN OF 
                 TRUE  : (aptr : APTR);
                 FALSE : (pptr : colourtablePtrType)
               END;

 rasterPtrType = ^raster;
 raster = PACKED ARRAY[0..RASSIZE] OF BYTE;
 
 myplaneType = PACKED RECORD
                CASE BOOLEAN OF 
                 TRUE  : (aptr : APTR);
                 FALSE : (rptr : rasterPtrType)
               END;
 
 mybaseType = PACKED RECORD
               CASE BOOLEAN OF 
                TRUE  : (libptr : LibraryPtrType);
                FALSE : (gfxptr : GfxBasePtrType)
              END;
 
VAR
 oldview       , 
 view          : ViewPtrType;
 vport         : ViewPortPtrType;
 colmap        : ColorMapPtrType;
 rinfo         : RasInfoPtrType;
 bitmap        : BitMapPtrType;
 base          : mybaseType;
 i, j          : INTEGER;
 colourpalette : paletteType;
 linfo         : Layer_InfoPtrType;
 layername     ,
 libname       : STRING;
 layer         : PACKED ARRAY[1..NLAYERS] OF LayerPtrType;
 rport         : RastPortPtrType;
 brc           : BOOLEAN;
 displaymem    : myplaneType;
  
INCLUDE 'exec/libraries';
INCLUDE 'graphics/routines';  
INCLUDE 'graphics/blitter';
INCLUDE 'graphics/copper';
INCLUDE 'graphics/rastport';
INCLUDE 'graphics/text';
INCLUDE 'graphics/view';
INCLUDE 'libraries/gfx';
INCLUDE 'libraries/layers';


PROCEDURE UnableToAccess( name : STRING );
BEGIN
 WRITELN( 'Unable to access ', name );
 HALT( 10 )
END;


PROCEDURE tidyup( rc : INTEGER );
VAR
 i : INTEGER;
BEGIN
 LoadView( oldview );              { Restore the old view }

 FOR i := 1 TO NLAYERS DO
  IF layer[i] <> NIL
  THEN DeleteLayer( linfo, layer[i] );

 DisposeLayerInfo( linfo );

 FOR i := 0 TO DEPTH
 DO FreeRaster( bitmap^.Planes[i], WIDTH, HEIGHT );

 FreeColorMap( colmap );
 FreeVPortCopLists( vport );
 FreeCprList( view^.LOFCprList );
 CloseLibrary( GetGfxBase );
 HALT( rc )
END;


FUNCTION CreateLayer( x0, y0, x1, y1 : INTEGER ) : LayerPtrType;
VAR
 lp : LayerPtrType;
BEGIN
 lp := CreateUpfrontLayer( linfo, bitmap, 
                           x0, y0, x1, y1, LAYERSMART, NIL );

 IF lp = NIL
 THEN tidyup( 10 );

 CreateLayer := lp
END;


PROCEDURE delay( time : INTEGER );
VAR
 i : INTEGER;
BEGIN
 FOR i := 0 TO time * 100 DO;
END;


BEGIN
 { Open the Graphics library for the Graphics routines }

 libname := 'graphics.library';
 SetGfxBase( OpenLibrary( libname, 0 ) );
 IF GetGfxBase = NIL
 THEN UnableToAccess( libname );
 
 { Open the Layers library for the Layers routines }

 libname := 'layers.library';
 SetLayersBase( OpenLibrary( libname, 0 ) );
 IF GetLayersBase = NIL
 THEN UnableToAccess( libname );

 { Save the current view so that it can be restored later }

 base.libptr := GetGfxBase;
 oldview := base.gfxptr^.ActiView;

 { Allocate a layerinfo record to keep track of my layers }

 linfo := NewLayerInfo;
 IF linfo = NIL
 THEN UnableToAccess( 'layer info' );

 { Initialise the view, and link it into the initialised viewport }

 NEW( view );  InitView( view );
 NEW( vport ); InitVPort( vport );
 view^.ViewPort := vport;

 WITH vport^ DO
 BEGIN
  NEW( rinfo ); RasInfo := rinfo; DWidth := WIDTH; DHeight := HEIGHT
 END;

 { Initialise the bitmap for the rasinfo and rastport }

 NEW( bitmap );
 InitBitMap( bitmap, DEPTH, WIDTH, HEIGHT );

 WITH rinfo^ DO
 BEGIN
  BitMap := bitmap; RxOffset := 0; RyOffset := 0; Next := NIL
 END;

 { Initialise the colour palette to black, red, green and blue }

 colmap := GetColorMap( 4 );
 vport^.ColorMap := colmap;

 colourpalette.aptr := colmap^.ColorTable;

 WITH colourpalette DO
 BEGIN
  pptr^[0] := $X000; pptr^[1] := $XF00;
  pptr^[2] := $X0F0; pptr^[3] := $X00F;
 END;

 { Allocate DEPTH bitplanes for the bitmap }

 FOR i := 0 TO DEPTH DO
 BEGIN
  bitmap^.Planes[i] := AllocRaster( WIDTH, HEIGHT );
  IF bitmap^.Planes[i] = 0
  THEN UnableToAccess( 'raster' );
 END;

 { Construct the initial copper instruction list and then merge   }
 { initial lists to form the final copper list in the view record }

 MakeVPort( view, vport );
 MrgCop( view );

 {$R- Avoid range checks whilst clearing the display area }
 FOR i := 0 TO DEPTH DO
 BEGIN
  displaymem.aptr := bitmap^.Planes[i];

  FOR j := 0 TO RASSIZE
  DO displaymem.rptr^[j] := 0;
 END;
 {$R+}

 LoadView( view );     { Load the black display area }

 { Create three smart refresh layers at the specified }
 { positions and then draw to each layer in turn.     }

 layer[1] := CreateLayer(  5,  5,  85,  65 );
 layer[2] := CreateLayer( 25, 25, 105,  85 );
 layer[3] := CreateLayer( 45, 45, 125, 105 );

 FOR i := 1 TO NLAYERS DO
 BEGIN
  rport := layer[i]^.rp;
  SetAPen( rport, i );
  SetDrMd( rport, JAM1 );
  RectFill( rport, 0, 0, 79, 59 );
  SetAPen( rport, 0 );
  Move( rport, 10, 35 );
  layername := CONCAT( 'Layer ', CHR( ORD( '0' ) + i ) );
  Text( rport, layername, LENGTH( layername ) )
 END;

 delay( 120 );
 brc := BehindLayer( linfo, layer[3] );

 delay( 120 );
 brc := UpfrontLayer( linfo, layer[1] );

 delay( 120 );
 FOR i := 0 TO 12 DO
 BEGIN
  MoveLayer( linfo, layer[2], 1, 5 );
  delay( 60 )
 END;

 delay( 480 );
 tidyup( 0 )
END.
