← ST-Computer 05 / 1986

Einführung in GEM (Teil 4)

Kurse

  • Clipping
  • Definieren eines Füllmuster
  • variable Zeichengröße
  • weitere Mausroutinen

Clipping

Bei intensiver Nutzung der GEM-Routinen kann es schon manchmal zu unangenehmen Begleiterscheinungen kommen, einfach gesagt, zu einem Programmabsturz. Sei es durch nicht initialisierte AES-Befehle oder durch falsche Parameter bei der Bildschirmausgabe. Gegen die zweite Ursache, die auftritt, wenn Ausgabebefehle einen Bereich weit außerhalb des Bildschirms ansprechen, existiert eine Routine, die die ßildschirmausgabe auf einen bestimmten Bereich beschränkt. Dadurch werden alle illegalen Bildschirmkoordinaten eliminiert. Natürlich kann auch ein kleiner Ausschnitt gewählt werden. Die darauffolgenden GEM-Grafikbefehle finden dann nur innerhalb des definierten Bereiches statt. Die Größe des Ausschnittes wird in diesem Unterprogramm in den Variablen ’XPOSl; YPOS1; XPOS2; YPOS2’ angegeben. Diese Routine arbeitet nur mit den GEM-Routinen zusammen, bei Basic-Ausgabebefehlen wird das Clipping nicht beachtet, bzw. sogar ausgeschaltet, so daß nachfolgende GEM-Ausgaberoutinen den gesamten Bildschirm ansprechen. Das angegebene Beispiel demonstriert die Funktionsweise dieses Befehls. Prinzipieller Aufruf:

XPOS 1 = .. : YPOS1 = ..: XPOS2 = .. : YP0S2 : Gosub CLIPPING

Diese Routine erspart beispielsweise bei Kurvendiskussionen die ständige Abfrage, ob die errechneten Werte außerhalb des erlaubten Bereiches liegen, und erleichtern bzw. beschleunigen die Berechnung.

64200 CLIPPING: 64202 ' —> XPOS1, YPOS1, XPOS2, YPOS2 64204 poke contrl ,129 64210 poke intin, 1 'Ausschnitt ein (0=aus) 64212 poke ptsin ,XPOS1 '0 64214 poke ptsin+2,YPOS1 '0 64216 poke ptsin+4,XPOS2 '600 64218 poke ptsin+6,XPOS2 '400 64220 vdisys 64222 return 64224 '-------------------------------

Routine CLIPPING

Definieren des Füllmusters

Trotz der vielen vorgegebenen Füllmuster soll dennoch auf die Möglichkeit zum freien Definieren des Musters hingewiesen werden. Bei dem Füllmuster handelt es sich um ein 16^ 16 Bit großes Muster, das bei allen ausfüllenden Grafikoperationen zur Geltung kommt. Dazu gehören neben den Basic-Befehlen ’PCIRCLE; PELLIPSE; FILL’ auch die schon zuvor besprochenen GEM-Routinen ’RECHTECK’, ’RECHTECKRUND’ und 'POLYGON’.

Die Werte des Füllmusters, bestehend aus 16 Worten (2 Byte), werden hierbei in Data-Zeilen abgelegt und mit dem dazugehörenden Namen versehen. Die Definition des neuen Musters geschieht durch:

Restore MUSTER Gosub FUELLMUSTER

Die Aktivierung dieses Musters wird durch ’COLOR 1,1,1,1,4 vorgenommen.

63500 FUELLMUSTER: 63502 ' —> restore MUSTER 63504 poke contrl,112 63506 poke contrl+6,16 63508 for st=0 to 30 step 2 63510 read muster 63512 poke intin+st,muster 63514 next : vdisys 63516 return 63518 ’---------------------

Routine FÜLLMUSTER

5 ’merge "FUELLMUSTER.bas“ 6 ’merge “RECHTECK.bas“ 7 ’merge “RECHTECKRUND.bas“ 9 ' 10 fullw 2 :clearw 2 20 WURM: 30 data 0,8064,16320,26208,30560,32736 40 data 29132,16318,8054,7782,7372,7384 50 data 4080,2022,60,24 60 RESTORE WURM: gosub fuellmuster 70 color 1 , 1 , 1 , 1,4 80 pellipse 130,100,100,60 90 ' 100 xpos1= 270:ypos1-30 : xpos2=350:ypos2=300 110 gosub rechteck 120 ' 130 xpos1 — 400:ypos1 = 200: xpos2=500:ypos2=300 140 fuell=1: gosub rechteckrund 150 ' 160 warte= inp(2) 170 end

Listing 2: Definition eines Füllmusters

Zeichenhöhe

Zwei der interessantesten GEM-Routinen sind laut Leserzuschriften — die zum Verändern der Schriftart und der Schriftgröße, welche schon im ersten Teil des Kurses besprochen wurden. Eine weitere Routine erlaubt auf dem Monochrommonitor die Größendefinition des Zeichensatzes in 24 Stufen (siehe Bild). Die Routine arbeitet mit allen Schriftarten zusammen (kursiv, ...). Alle Schriftarten, die von der Normalgröße abweichen, können nicht per ’PRINT’ ausgegeben werden, da dieser Befehl nur auf Standardgröße ausgelegt ist. Hierzu dient die GEM-Ausgaberoutine.

Der Aufruf erfolgt durch:

ZEICHENHOEHE = (3 .. 26) : Gosub ZEICHENHOCH

Bei monochromem Monitor beträgt der Parameter der normalen Schrifthöhe ’12’, bei einem Farbmonitor hingegen, auf Grund der niedrigeren Vertikalauflösung, ’6’. Die unterschiedlichen Auflösungsstufen eines Farbmonitors sind auch dafür verantwortlich, daß die entstehenden Schriftgrößen nicht denen eines Monochrommonitors entsprechen, sondern grundsätzlich größer sind.

5 ’merge "ZEICHENHOCH.bas“ 6 ’merge "TEXTAUSGABE.bas“ 7 ’merge "GRAFIKAUSSCHNITT.BAS" 9 ' 10 fullw 2:clearw 2 20 XPOS1=0:YPOS1=0:XPOS2=600:YP0S2=360 30 gosub grafikausschnitt 40 for zeichenhoehe= 1 to 12 50 gosub zeichenhoch 60 xpos=30 :ypos=25*zeichenhoehe 70 text$=“Sehriftgroesse !" 80 gosub textausgabe: next 90 xpos=300: ypos=0 100 for zeichenhoehe= 13 to 26 110 gosub zeichenhoch 120 ypos=ypos+zeichenhoehe+4 : gosub textausgabe:next 130 zeichenhoehe=13: gosub zeichenhoch 140 warte=inp(2):end

Listing 3: Einstellen der Zeichenhöhe

65300 ZEICHENHOCH: 65302 '--> ZEICHENHOEHE 65304 poke contrl,12 65306 poke ptsin+2,zeichenhoehe 65308 vdisys 65310 return 65312 ' ------------------------

Routine ZEICHENHÖHE

Entsprechendes gilt für die Routine 'Schriftgröße’ die schon im ersten Teil erwähnt wurde. Der Unterschied zwischen diesen zwei Routinen besteht in der Schrittweite, in der die verschiedenen Größen angegeben werden können.

'Schriftgroesse' läßt nur sechs Größenstufen zu, während ’Schrifthöhe’ durch Bildung von Zwischenstufen eine fast kontinuierliche Größe ermöglicht, bei denen einige allerdings etwas unsauber abgebildet werden. Für bestimmte Anwendungen ist es aber sicher von Vorteil, eine passende Schrift auszuwählen. Bei mittlerer oder niedriger Auflösungsstufe (Farbe) stehen die kleinsten Größen nicht zur Verfügung.

Rahmung

Normalerweise werden alle Grafikoperationen, die ein Füllmuster beinhalten, mit einer Linie umrahmt. Mit der folgenden Routine kann dieser Effekt ausgeschaltet werden.

RAHMEN = (0 , 1) : Gosub UMRAHMUNG

Bei Aneinanderreihung von Füllkörpern entsteht so eine geschlossene Fläche.

Die Funktion arbeitet mit folgenden Basic- bzw. GEM-Befehlen zusammen:

  • pcircle

  • pellipse

  • rechteck

  • rechteckrund

  • polygon

    64250 UMRAHMUNG: 64252 '--> RAHMEN (0,1) 64254 POKE contrl,104 64256 poke intin,rahmen 64258 vdisys 64260 return 64262 ’---------------

Routine UMRAHMUNG

5 ’merge ”UMRAHMUNG.bas " 9 ' 10 fullw 2: clearw 2 20 color 1, 1, 1,3,3 30 rahmen=1 :gosub umrahmung 40 pcircle 150,150,100,0,2800 50 rahmen=0 :gosub umrahmung 60 pcircle 400,150,100,0,2800 70 warte = inp(2) 80 end

Listing 4: Umrahmung ein/aus

Mausbefehle

Das AES bietet auch einige interessante Befehle, die von der Maus unterstützt werden. Neben der auch im VDI enthaltenen 'Position & Tastenabfrage’, existiert eine Routine, die kontrolliert, ob sich die Maus in einem bestimmten Rechteck befindet, und eine weitere, die das Markieren von Bildschirmbereichen ermöglicht.

Dabei ist zu beachten, das AES-Routinen einer Initialisierung durch ’INIT’ bedürfen.

# Routine INIT 62900 INIT: 62902 aes#=9b 62904 control = peektaesH) 62906 global = peek(aes#+4 ) 62908 giritiri = peek(aes#+8 ) 62910 gintaut = peek(aes#+12) 62912 addriri = peek(aes#+16) 62914 addrout = peek(aes#+20) 62916 return 62918 ’---------------------

MOUSE

Diese Routine enthält die gleichen Funktionen wie die VDI-Routine zur Mausabfrage. Mit ihr kann die Position der Maus und die Information über die Maustasten ermittelt werden. Zusätzlich gibt sie noch den Status der 'CONTROL, ALTERNATE’ und den beiden 'SHIFT’-Tasten zurück.

# Routine MOUSE 62550 MOUSE: 62552 ' <— MAUSX l MAUSY 62554 ' <— TASTE; KEY 62556 mausx=peek(gintout+2)-1 62558 mausy=peek(gintout+4)-38 62560 taste=peek(gintout+6) 62562 key = peek(gintout+8) 62564 gemsys 79 62566 return 62568 ’------------------------

Der Aufruf erfolgt durch:

Gosub MOUSE

Die Informationen über Mausposition, Maustasten und der Tastatur sind anschließend in den Variablen MAUSX, MAUSY, TASTE und KEY enthalten. Die erhaltenen Werte sind folgendermaßen zu interpretieren.

TASTE:

Taste Wert
links 1
rechts 2
links + rechts 3

KEY:

Taste Wert
Shift rechts 1
Shift links 2
Control 4
Alternate 8
5 ' merge "INIT.bas“ 6 ' merge “MOUSE.bas“ 9 ' 10 gosub init 20 Start: 30 gosub mouse 40 print mausx,mausy,taste,key 50 goto Start

Listing 5: Abfrage der Mausposition

Mausereignis

Diese Routine kontrolliert die Anwesenheit des Maussymbols in einem bestimmten, vordefinierten Rechteck. Der Anfangspunkt wird in XPOS und YPOS übergeben und legt die linke obere Ecke fest, die Variablen BREIT und HOCH bestimmen die horizontale und vertikale Ausdehnung des Bildschirmausschnittes, auf den die Routine reagiert. Dazu existieren zwei verschiedene Modi. Entweder wartet die Routine, bis die Maus den Bildschirmausschnitt betritt oder, bis sie ihn verläßt. Dies wird in Speicherzelle ’GINTIN’ festgelegt, wobei eine Null bewirkt, daß die Routine wartet, bis die Maus in den Bereich eintritt, eine Eins entsprechend das Gegenteil. Der Aufruf erfolgt durch:

XPOS1 = .. : YPOS1 = ..: BREIT = .. : HOCH = ..: GOSUB EVENTMAUS 62500 EVENTMAUS: 62502 ' —> XPOS1 ; YPOS1 62504 ’ —> BREIT ; HOCH 62506 poke gintin,0 62508 poke gintin+2,xpos1+1 62510 poke gintin+4,ypos1+38 62512 poke gintin+6,breit 62514 poke gintin+8,hoch 62516 gemsys 22 62518 return 62520 '---------------------- 5 'merge "INIT.bas" 6 'merge "EVENTMAUS.bas” 7 'merge "SHOWMAUS.bas" 8 'merge "RECHTECK.bas" 9 ' 10 gosub init 20 fullw 2 : color 1,1,1,3,3 30 xpos1=100:ypos1=100:xpos2=150:ypos2=120 40 breit = 50 : hoch = 20 50 Start: 55 gosub rechteck 60 gosub showmaus 70 gosub eventmaus: 80 out 2,7 : goto Start 90 end

Routine EVENTMAUS

Listing 6: Warten auf Mausereignis

63030 SHOWMAUS: 63032 poke contrl,122 63034 poke intin,0 63036 vdisys 63038 return 63040 '--------------- 63042 HIDEMAUS: 63044 poke contrl,123 63046 vdisys 63048 return 63049 '--------------- 64000 RECHTECK: 64002 ' --> XPOS1 ; YPOS1 ; XPOS2 ; YP0S2 64004 poke contrl ,11 64006 poke contrl+2 ,2 64008 poke contrl+6 ,0 64010 poke contrl+10,1 64012 poke ptsin ,XPOS1 +1 64014 poke ptsin+2,YPOS1 +38 64016 poke ptsin+4,XPOS2 +1 64018 poke ptsin+6,YP0S2 +38 64020 vdisys 64022 return 64024 '-------------------------------------

Routine RECHTECK Routinen SHOWMAUS / HIDEMAUS

Definieren eines Rechteckes

62200 RUBBERBOX: 62202 '—> MAUSX ; MAUSY 62204 ' <— BREIT ; HOCH 62206 poke gintin , mausx+1 62208 poke gintin+2 , mausy+38 62210 poke gintin+4 , 1 62212 poke gintin+6 , 1 62214 AES.3: gemsys 70 62216 breit = peek(gintout+2) 62218 hoch = peek(gintout+4) 62220 if hoch<3 or breit<3 then goto AES.3 62222 return 62224 ' -----------------------------------------

Routine RUBBERBOX

5 ' merge "INIT.bas" 6 ’ merge "MOUSE.bas“ 7 ' merge "RUBBERBOX.bas" 10 gosub INIT 20 openw 2:clearw 2 30 Start: gosub MOUSE 40 if taste=l then gosub rubberbox else goto start 50 ? "Die Box ist "breit" breit und "hoch“ hoch" 60 end

Listing 7: Rechteckdefinition mit Maus

Rubberbox

Zwei weitere, nützliche Routinen dienen zum Festlegen eines Rechtecks mit der Maus. Die erste erzeugt ein Rechteck, dessen eine Ecke fixiert ist, wobei die andere, bei gedrückter Maustaste, der Mausbewegung folgt.

Die linke obere Ecke wird durch Anklicken mit der Maus bestimmt. Daraufhin entsteht ein gestricheltes Rechteck, das den Bewegungen der Maus folgt. Dabei muß die linke Maustaste gedrückt bleiben.

Sobald sie losgelassen wird, gibt die Routine die Breite und Höhe des momentan markierten Rechtecks zurück.

Der Aufruf erfolgt durch:

Gosub RUBBERBOX

Bevor diese Routine angesprochen wird, sollte mit Hilfe des ’MOUSE’-Unterprogrammes abgefragt werden, ob die linke Maustaste gedrückt wurde, um den Startpunkt des Rechtecks an die betreffende Stelle zu legen. ’RUBBERBOX’ entnimmt dann den Startpunkt aus den von der MOUSE-Routine stammenden Variablen MAUSX und MAUSY.

Drag box

Diese Routine dient zum Verschieben eines Rechtecks. Die Größe des zu verschiebenden Rechtecks wird dabei vorgegeben (BREIT,HOCH). Es ist zweckmäßig, die Anfangskoordinaten mittels der MOUSE-Routine festzulegen, damit der Anfangspunkt des Rechtecks auch der Mausposition entspricht. Die Routine ist deshalb darauf ausgelegt, daß sie den Anfangspunkt den Variablen MAUSX und MAUSY entnimmt. Weiterhin ist diese Routine in der Lage, einen Bereich zu kennzeichnen, den dieses Rechteck nicht verlassen kann. Definiert wird er in X.MIN, Y.MIN und X.MAX, YMAX.

Aufruf durch

X.MIN = .. : Y.MIN = .. X.MAX = .. ; Y.MAX = .. BREIT = .. : HOCH = .. Gosub DRAGBOX

Die Routine gibt in den Variablen XPOS1 und YPOS1 die neue Lage des Rechtecks an das Hauptprogramm zurück.

Bei dem Beispielprogramm hierzu kommen neben der Rechteckroutine zwei weitere VDI-Routinen zur Geltung. Sie sorgen dafür, daß die Maus bei gegebener Zeit sichtbar bzw. unsichtbar wird, da sonst das Rechteck an dem Punkt, wo es mit der Maus überlappt, gelöscht würde. Um das zu verhindern, wird vor Aufruf einer GEM-Ausgaberoutine, die Maus mittels ’Gosub HIDEMAUS’ aus- und anschließend durch ’Gosub SHOWMAUS’ wieder eingeschaltet.

Aus diesem Beispiel wird ersichtlich, daß gerade durch Kombination der einzelnen GEM-Routinen die besten Ergebnisse erzielt werden. Auch die hier angeführten Demoprogramme demonstrieren lediglich die prinzipielle Arbeitsweise der einzelnen Routinen, die sicherlich in fast allen Programmen ihre Anwendung finden und Ihnen helfen, den ATARI ST ein wenig mehr auszureizen.

Zur umfangreichen GEM Nutzung ist aber trotzdem die Verwendung einer anderen Programmiersprache (C, Pascal) sehr empfehlenswert bzw. unbedingt anzuraten, da einerseits nicht alle Routinen im Basic ansprechbar sind und andererseits die Handhabung wesentlich bequemer ist, nicht zuletzt auch wegen des Geschwindigkeitsgewinns einer Compilersprache. So mag sich mancher C-Programmierer sicher gewundert haben, wieso man die GEM-Routinen, die in C ohne Kompromisse aufrufbar sind, in einer Sprache anwendet, die für solche Anwendungen weniger geeignet ist. Den Basic-Pro-grammierern aber hoffen wir, eine Hilfe für die ausgedehntere Nutzung ihres Rechners gegeben zu haben, und nicht zuletzt einen Anreiz auf die GEM-Programmierung in C oder Pascal.

★ Ende des Kurses ★

62250 DRAGBOX: 62252 ’ —> BREIT ; HOCH 62254 ’ —> X.MIN ; Y.MIN 62256 ' —> X.MAX ; Y.MAX 62258 ’ <— XPOS1 5 YPOS1 62260 poke control+2,8 62262 poke control+4,3 62264 poke gintin, breit 62266 poke gintin+2, hoch 62268 poke gintin+4, mausx+1 62270 poke gintin+6, mausy+38 62272 poke gintin+8, x.min+1 62274 poke gintin+10,y.min+38 62276 poke gintin+L2,x.max+1 62278 poke gintin+14,y.max+38 62280 gemsys 71 62282 xpos1=peek(gintout+2)-1 62284 ypos1=peek(gintout+4)-38 62286 return 62288 ’----------------------

Routine DRAGBOX

3 ’merge "INIT.bas" 4 ’merge "DRAGBOX.bas" 5 ’merge “MOUSE.bas" 6 ’merge "RECHTECK.bas" 7 'merge "SHOWMAUS.bas" 8 ’merge "HIDEMAUS.bas" 9 ' 10 gosub init 20 fullw 2:clearw 2: color 1,1,1,2,3 30 breit =200:hoch =150:x.min=100:y.min=100 40 x.max=500:y.max=250 50 gosub mouse 60 Start: gosub mouse 70 if taste=l then gosub dragbox else goto Start 80 xpos2 = xpos1+breit: ypos2 = ypos1+hoch 90 gosub hidemaus: gosub rechteck 100 gosub showmaus 110 gotoxy 0,0 120 ?"Das Rechteck befindet sich nun bei " xpos1,ypos1 130 end

Listing 8: Rechteckverschieben mit Maus