#Logo Gadget2-13:pinsel/ag.prog
#Titel Programmieren / PCQ-Pascal-Kurs Teil 3
#C31
#Font Frankfurter 16
  SYSTEMPROGRAMMIERUNG IN PCQ-PASCAL
              TEIL 3
#Font topaz 8
                                                 Von Andreas Neumann
#C31
Bisherige Kursteile :
#C21

    Teil I   : Gadget Nr.7 / Voraussetzungen,Screens,Windows
    Teil II  : Gadget Nr.8 / Einfache Grafikausgabe


   Was für ein Tag ! Stoltenberg  ist  zurückgetreten  und  ich  muß
jetzt  noch  schnell  Teil drei dieses Kurses fertigstellen.... Sch­
witz. Also gut, wie versprochen : noch einige Grafikbefehle.

Im Include-File "Graphics/Text.i" finden sich unter anderem:

GText (window^.RPort,string,count) - Gibt einen Text, der in der
                                     Variable string gespeichert ist
                                     count Zeichen lang aus.
                                     Normalerweise setzt man count:=
                                     StrLen (string);

TextLength (window^.RPort,string,count) - Gibt die Anzahl der Pixel an,
                                          die von count Zeichen des
                                          Strings string benötigt
                                          werden würden. Normalerweise
                                          Zeichen*8, aber seit Kick2.0
                                          sollte man da vorsichtig sein...

    In  den  Includes  "Graphics/Pens.i"  und  "Graphics/RastPort.i"
erschließt sich uns eine neue Dimension der Grafikausgabe :

   Gefüllte Flächen.  Damit  man  diese  darstellen  kann,  muß  man
vorerst  eine sogenannte TmpRas-Struktur einrichten und dem Rastport
einverleiben. Dies geschieht mit :

InitTmpRas (TmpRasPtr , Buffer , Buffersize) - Initialisiert eine solche
                                               Struktur. Wie sieht das
                                               Teil nun aus ?

#C10
    TmpRas = record
        RasPtr  : Address;
        Size    : Integer;
    end;
#C21

   Yo, was wollen uns diese Variablen sagen ? Nun, RasPtr  wird  von
InitTmpRas  besetzt  und  Size  können  wird  mit  der im File "Gra­
phics/Gfx.i" besetzt. Also : Size:=RASSIZE (Breite,Hoehe);

   Buffer ist ein Zeiger auf ein vorher zu belegendes Raster. Dieses
wird mit Buffer:=AllocRaster (Breite,Hoehe) belegt.

   Buffersize letztendlich kann wieder mit RASSIZE berechnet werden:
Buffersize:=RASSIZE (Breite,Hoehe).

   Normalerweise verwendet man für Breite und Höhe die entsprechen­
den Ausmaße des Fensters.

Das ganze wird dann in die Windowstruktur eingebunden :

#C10
window^.RPort^.TmpRas:=TmpRasPtr;
#C21

Flood (window^.RPort,mode,x,y) - füllt eine zusammenhänge Fläche, in der
                                 der Punkt P (x/y) enthalten ist. Mode
                                 wird in der Regel 1 sein, Mode 0 benötigt
                                 eine Umrandungslinie mit dem AOlPen und
                                 ist an sich unnötig....

   Es gibt noch einige andere Flächenformen, die zwar  einfacher  zu
hand-haben  sind,  die  aber  noch  einiges weiteres an Strukturkram
benötigen. Deshalb : heute nicht ! Ein anderes Mal mehr dazu.

   Nun wollen wir uns zwei Procedure schreiben, die uns  die  Arbeit
verkürzen. Nämlich in etwa so :

#C10
PROCEDURE Print (rp : Address; xs , ys : Short; stext : String);

 BEGIN
  Move (rp,xs,ys);
  GText (rp,stext,StrLen(stext));
 END;
#C21

 und

#C10
 PROCEDURE InitialisiereRaster (itmpras : TmpRasPtr; VAR ARaster : Address;
                            width , height : Short ; swindow : WindowPtr);

 BEGIN
  ARaster:=AllocRaster(width,height);
  WITH itmpras^ DO
  BEGIN
   RasPtr := NIL;
   Size := RASSIZE (width,height);
  END;
  InitTmpRas (itmpras , ARaster , RASSIZE (width,height));
  swindow^.RPort^.TmpRas := itmpras;
 END;
#C21

   Und nicht vergessen : Wenn man das Programm beendet, dann  sollte
 man das belegte Raster mit FreeRaster (Buffer,Breite,Hoehe); wieder
freigeben.

Machen wir halt mal ein kloines Beispiel :

#C10
        Program KursProgramm;

        { Listing für den AMIGAGadget - Pascalkurs ,            }
        { Dritte Schritte in der Grafikprogrammierung           }

        {$I "Include:Intuition/Intuition.I" }
        {$I "Include:Exec/Libraries.I"      }
        {$I "Include:Graphics/Graphics.I"   }
        {$I "Include:Libraries/Dos.I"       }
        {$I "Include:Graphics/Pens.I"       }
        {$I "Include:Graphics/Rastport.I"   }
        {$I "Include:Utils/Stringlib.I"     }

        VAR
                myscreen : ScreenPtr;
                mywindow : WindowPtr;



        PROCEDURE Line (rp : Address ; xs , ys , xe , ye : Short);

        BEGIN
         Move (rp , xs , ys); Draw (rp , xe , ye);
        END;


        PROCEDURE Box (rp : Address ; xs , ys , xe , ye : Short);

        BEGIN
         Line (rp,xs,ys,xe,ys); Line (rp,xe,ys,xe,ye);
         Line (rp,xe,ye,xs,ye); Line (rp,xs,ye,xs,ys);
        END;

        PROCEDURE Print (rp : Address; xs , ys : Short; stext : String);

        BEGIN
         Move (rp,xs,ys);
         GText (rp,stext,StrLen(stext));
        END;

        PROCEDURE InitialisiereRaster (itmpras : TmpRasPtr;
                                       VAR ARaster : Address;
                                       width , height : Short ;
                                       swindow : WindowPtr);

        BEGIN
         ARaster:=AllocRaster(width,height);
         WITH itmpras^ DO
         BEGIN
          RasPtr := NIL;
          Size := RASSIZE (width,height);
         END;
         InitTmpRas (itmpras , ARaster , RASSIZE (width,height));
         swindow^.RPort^.TmpRas := itmpras;
        END;


        PROCEDURE CloseDisplay;

        VAR i : Integer;

        { Sollte ein Teil des Displays offen sein, dann wird er von }
        { dieser Routine geschlossen.                               }

        BEGIN
         IF mywindow<>NIL THEN
          CloseWindow (mywindow);
         IF myscreen<>NIL THEN
          CloseScreen (myscreen);
         IF GfxBase<>NIL THEN
          CloseLibrary (GfxBase);
        END;


        PROCEDURE BreakProgram (reason : STRING);

        { Diese Routine schließt alles bisher geöffnete, druckt den }
        { Fehlergrund aus und bricht dann das Programm ab.          }

        BEGIN
         CloseDisplay;
         WRITELN ('Program error : ',reason);
         Exit (42);
        END;

        PROCEDURE OpenLibs;

        CONST   GraphicName : String = "graphics.library";

        BEGIN
         GfxBase:=OpenLibrary (GraphicName,0);
        END;


        PROCEDURE OpenDisplay;

        { Diese Routine erstellt ein Display.                       }

        CONST
                mynewscreen : NewScreen = (0,0,640,256,2,0,1,HIRES,
                                            CUSTOMSCREEN_f,NIL,
                                            NIL,NIL,NIL);

        NewWin   : NewWindow =  (100,50,320,128,0,1,0,
                                SMART_REFRESH+WINDOWDRAG+
                                ACTIVATE+SMART_REFRESH,NIL,NIL,
                                "Unsere neuen schicken Befehle !",
                                NIL,NIL,0,0,0,0,CUSTOMSCREEN_f);

        BEGIN
          myscreen := OpenScreen (Adr(mynewscreen));
          IF myscreen=NIL THEN BreakProgram ("Couldn't open Screen");
          NewWin.Screen:=myscreen;
          mywindow := OpenWindow (Adr(NewWin));
          IF mywindow=NIL THEN BreakProgram ("Couldn't open Window");
        END;

        PROCEDURE NeueBefehle;

        {Demonstration der neuen Befehle.                           }

        VAR MyTmpRas : TmpRas;
            MyRaster : Address;
        BEGIN
         {Ganz am Anfang eine kleine Textausgabe                    }
         SetAPen (mywindow^.RPort,1);
         Print (mywindow^.RPort,10,20,"Hello World ! Let's have some");
         Print (mywindow^.RPort,10,28,"NEW GRAPHIC FUNCTIONS !!!");
         {Zuersteinmal Initialisierung der benötigten Strukturen.   }
         InitialisiereRaster (Adr(MyTmpRas),MyRaster,mywindow^.Width,
                              mywindow^.Height,mywindow);
         {Und dann einen Kreis, der von uns gefüllt wird !          }
         DrawCircle (mywindow^.RPort,60,70,20);
         Flood (mywindow^.RPort,1,60,70);
         {Auch noch ein gefülltes Dreieck....                       }
         Line (mywindow^.RPort,110,60,180,85);
         Line (mywindow^.RPort,180,85,100,70);
         Line (mywindow^.RPort,100,70,110,60);
         Flood (mywindow^.RPort,1,120,65);
         {Und wieder ein wenig Text                                 }
         SetAPen (mywindow^.RPort,3);
         Print (mywindow^.RPort,10,110,"Das war's. See U later.");
         FreeRaster (MyRaster,mywindow^.Width,mywindow^.Height);
        END;

        PROCEDURE WarteEinWenig;

        BEGIN
          Delay (1000);
        END;

        BEGIN
          OpenLibs;
          OpenDisplay;
          NeueBefehle;
          WarteEinWenig;
          CloseDisplay;
        END.
#C21
#Seitenende
   Es gäbe noch sehr viel über Grafik und ihre Anwendung  zu  erzäh­
len,  doch finde ich es wichtiger, die Brücke zum Anwender zu schla­
gen, will sagen, im nächsten Teil mit dem Kapitel Messages zu begin­
nen. (Klingt geheimnisvoll, oder ?) Für heute  soll's  genügen,  war
zwar  ein  wenig kürzer als sonst, aber wenn hier nicht bald tonnen­
weise positive Leserbriefe beim Nils eintreffen,  dann  wird's  noch
weniger.... (DROH !)

   Ansonsten noch eine Anmerkung : es gibt jetzt PD-Serie,  die  nur
Pascal-Programme  enthält  (ähnlich AMOK mit Modula#2) : PURITY. Sie
wird von Robert Martignoni und Bernd  Künnen  zusammengestellt  (ich
stehe  mit  beiden in Kontakt). Wer Interesse an den Puritys, Kritik
oder Lob für diesen Kurs, Verbesserungsvorschläge  oder  Fragen  (es
gibt keine dummen Fragen !!) hat, melde sich entweder bei mir

    Andreas Neumann ; Auf dem Ruhbühl 151 ; 7997 Immenstaad

  oder im Gadget. Bye.
#C31
                             1992 by Andreas Neumann für AmigaGadget
