MODULE LayersDemo;

(** ------------------------------------------------------------------

           Commodore Amiga layers library demonstration module

      (c) Copyright 1986 Modula-2 Software Ltd.  All Rights Reserved
      (c) Copyright 1986 TDI Software, Inc.      All Rights Reserved

    ------------------------------------------------------------------ **)


(* VERSION FOR COMMODORE AMIGA

     Original Author : Paul Curtis, Modula-2 Software Ltd.  02-Jun-86

     Version         : 0.01a  08-Dec-86  Martin Fisher, Modula-2 Software Ltd.
                         Version 3.00a library change modifications.
                       0.00a  02-Jun-86  Paul Curtis, Modula-2 Software Ltd.
                         Original from Rom Kernel Manual.

  *)


FROM GraphicsBase IMPORT GfxBasePtr;
FROM LayersLibrary IMPORT LayersBase, LayersName, NewLayerInfo,
  CreateUpfrontLayer, MoveLayer, LayerPtr, LayerInfoPtr,
  BehindLayer, UpfrontLayer, DeleteLayer, DisposeLayerInfo,
  LayerSmart;
FROM GraphicsLibrary IMPORT GraphicsBase, GraphicsName, BitMap,
  InitBitMap, Jam1;
FROM Views IMPORT View, ViewPtr, ViewPort, InitView, InitVPort, LoadView,
  MakeVPort, MrgCop, FreeVPortCopLists;
FROM Copper IMPORT FreeCprList;
FROM Colors IMPORT ColorMapPtr, GetColorMap, FreeColorMap;
FROM Rasters IMPORT RasInfo, AllocRaster, FreeRaster, RastPortPtr;
FROM Text IMPORT Text;
FROM Pens IMPORT Move, Draw, SetAPen, SetDrMd, RectFill;
FROM Libraries IMPORT OpenLibrary, CloseLibrary;
FROM DOSProcessHandler IMPORT Delay;
FROM SYSTEM IMPORT ADDRESS, NULL, ADR, BYTE;
FROM InOut IMPORT WriteString, WriteLn;

CONST
  DEPTH  = 2;  
  WIDTH  = 320;
  HEIGHT = 200;

CONST
  BLACK = 0000H;
  RED   = 0F00H;
  GREEN = 00F0H;
  BLUE  = 000FH;

CONST
  FLAGS = LayerSmart;

VAR
  oldview: ViewPtr;   (* save pointer to old view so can go back to sys *)
  v: View;
  vp: ViewPort;
  cm: ColorMapPtr;    (* pointer to colormap structure, dynamic alloc *)
  ri: RasInfo;
  b: BitMap;

  rp: ARRAY [0..2] OF RastPortPtr;         (* rastport for each layer *)

  displaymem: POINTER TO BYTE;
  gfxbase: GfxBasePtr;

  li: LayerInfoPtr;
  layer: ARRAY [0..2] OF LayerPtr;

  i, j: CARDINAL;

  PROCEDURE RasSize(w, h: CARDINAL): CARDINAL;
  BEGIN
    RETURN (h * CARDINAL(BITSET((w + 15) DIV 8) * BITSET{1..15}));
  END RasSize;

BEGIN
  GraphicsBase := OpenLibrary(GraphicsName,0);
  IF GraphicsBase = NULL THEN
    WriteLn; WriteString("no graphics library");
    HALT
  END;

  LayersBase := OpenLibrary(LayersName,0); 
  IF LayersBase = NULL THEN
    WriteLn; WriteString("no layers library");
    HALT
  END;

  gfxbase := GraphicsBase;
  oldview := gfxbase^.ActiView; (* save current view, go back later *)
        
  li := NewLayerInfo();          (* get a LayerInfo structure *)
  IF li = NULL THEN
    WriteLn; WriteString("can't grab a new layer info");
    HALT;
  END;


  InitView(ADR(v));                   (* initialize view *)
  v.viewPort := ADR(vp);         (* link view into viewport *)
  InitVPort(ADR(vp));                 (* init view port *)
                                
  vp.dWidth := WIDTH;            (* now specify critical characteristics *)
  vp.dHeight := HEIGHT;
  vp.rasInfo := ADR(ri);
                                 (* init bit map (for rasinfo and rastport) *)
  InitBitMap(b,DEPTH,WIDTH,HEIGHT);
  ri.bitMap := ADR(b);
  ri.rxOffset := 0;              (* align upper left corners of display
                                    with upper left corner of drawing area *)
  ri.ryOffset := 0;
  ri.next := NULL;

  cm := GetColorMap(4);          (* 4 entries, since only 2 planes deep *)
  WITH cm^ DO
    colorTable^[0] := BLACK;
    colorTable^[1] := RED;
    colorTable^[2] := GREEN;
    colorTable^[3] := BLUE;
  END;

  vp.colorMap := cm;             (* link it with the viewport *)

  FOR i := 0 TO DEPTH-1 DO
    b.Planes[i] := AllocRaster(WIDTH,HEIGHT);
    IF b.Planes[i] = NULL THEN
      WriteLn; WriteString("not enough memory for bit planes");
      HALT;
    END;
  END;

  MakeVPort(ADR(v),ADR(vp));      (* construct copper instr (prelim) list *)
  MrgCop(ADR(v));                 (* merge prelim lists together into a real 
                                    copper list in the view structure. *)

  FOR i := 0 TO 1 DO
    displaymem := b.Planes[i];
    FOR j := 0 TO RasSize(WIDTH,HEIGHT)-1 DO
      displaymem^ := BYTE(0);
      INC(displaymem)
    END
  END;

  LoadView(ADR(v));

  (* now fill some boxes so that user can see something *)

  layer[0] := CreateUpfrontLayer(li^,b,5,5,85,65,FLAGS,NULL);
  IF layer[0] = NULL THEN HALT END;
        
  layer[1] := CreateUpfrontLayer(li^,b,20,20,100,80,FLAGS,NULL);
  IF layer[1] = NULL THEN HALT END;

  layer[2] := CreateUpfrontLayer(li^,b,45,45,125,105,FLAGS,NULL);
  IF layer[2] = NULL THEN HALT END;

  FOR i := 0 TO 2 DO      (* layers are created, now draw to them *)
    rp[i] := layer[i]^.rp;
    SetAPen(rp[i],i+1);
    SetDrMd(rp[i],Jam1);
    RectFill(rp[i],0,0,79,59);
  END;

  SetAPen(rp[0],0);
  Move(rp[0],5,30);
  Text(rp[0],"Layer 0",7);

  SetAPen(rp[1],0);
  Move(rp[1],5,30);
  Text(rp[1],"Layer 1",7);

  SetAPen(rp[2],0);
  Move(rp[2],5,30);
  Text(rp[2],"Layer 2",7);
        
  Delay(120);     (* 2 seconds before first change *)

  IF BehindLayer(li^,layer[2]^) THEN END;

  Delay(120);     (* another change 2 seconds later *)

  IF UpfrontLayer(li^,layer[0]^) THEN END;

  Delay(120);     (* another change 2 seconds later *)
  FOR i := 0 TO 29 DO
    MoveLayer(li^,layer[1]^,1,3);
  END;

  LoadView(oldview);              (* put back the old view *)
  DeleteLayer(li^,layer[2]^);
  DeleteLayer(li^,layer[1]^);
  DeleteLayer(li^,layer[0]^);

  DisposeLayerInfo(li^);
  CloseLibrary(GraphicsBase);

  FOR i := 0 TO DEPTH-1 DO
    FreeRaster(b.Planes[i],WIDTH,HEIGHT)
  END;
  FreeColorMap(cm);                       (* free the color map *)
  (* free dynamically created structures *)
  FreeVPortCopLists(ADR(vp));         
  FreeCprList(v.LOFCprList^);
END LayersDemo.
