Kurs jëzyka C (cz. 5.) ---------------------- MALOWANIE PO EKRANIE Kamil Iskra, Dariusz Ûbik W dzisiejszej czëôci zajmiemy sië rysowaniem. Wysokopoziomowe funkcje graficzne jako jednego z argumentów wymagajâ wskaúnika na RastPort (patrz "graphics/rastport.h"). Jest to struktura zawierajâca informacje niezbëdne do prac graficznych, jednak nas interesuje tylko czëôê danych w niej zawartych. Kaûde otwarte okno ma wîasny RastPort. Jego adres moûna znaleúê w polu "RPort" struktury "Window". RastPort moûna traktowaê jako "czarnâ skrzynkë", potrzebnâ do rysowania. Jest ona doôê wygodna. Uûywajâc róûnych funkcji graficznych, podajemy wspóîrzëdne punktów wzglëdem lewego górnego rogu RastPortu. Podanie wspóîrzëdnych "wystajâcych" poza RastPort nie powoduje ûadnych problemów -- funkcje graficzne narysujâ tylko tyle, ile sië zmieôci. W RastPorcie zapisane jest równieû poîoûenie kursora graficznego, tryb rysowania, aktualne kolory, wzór linii itp. Poîoûenie kursora zapisane jest w polach "cp_x" i "cp_y", po inicjalizacji RastPortu (w naszym wypadku otwarciu okna) kursor znajduje sië w punkcie (0, 0), co zwykle wypada na górnej listwie okna. Po dodaniu w tagu "WA_Flags" flagi "WFLG_GIMMEZEROZERO" niedogodnoôê ta znika, punkt (0, 0) wypada w lewym górnym rogu wnëtrza okna, ale obsîuga okien jest wolniejsza, a takûe wiëksze jest zapotrzebowanie na pamiëê, wiëc nie radzimy uûywaê tego atrybutu. Przy opisywaniu gadûetów pokaûemy, jak moûna sië obejôê bez pomocy GZZ. Kolor tîa jest odnotowany w polu "BgPen" (BPen), kolor "atramentu" w "FgPen" (APen). Nie wolno bezpoôrednio (instrukcjâ przypisania) zmieniaê kolorów, zapisanych w strukturze. Do tego celu przeznaczone sâ funkcje biblioteki "graphics.library": void SetAPen( struct RastPort *rp, unsigned long pen ); void SetBPen( struct RastPort *rp, unsigned long pen ); Pierwsza z nich zmienia kolor atramentu, druga kolor tîa. Obie funkcje wymagajâ jako argumentów wskaúnika na RastPort oraz numeru koloru. Dane zawarte w polach "FgPen" i "BgPen" moûna byîo odczytywaê. Zapisana tam wartoôê to numer koloru. Jednak od systemu 3.0 pojawiîy sië specjalne funkcje, zwracajâce numery kolorów jako wartoôê typu ULONG. Jest to przygotowane nieco na wyrost, poniewaû koôci AGA majâ oômiobitowy blitter, czyli 256 rejestrów kolorów, w zwiâzku z czym do zapisania koloru wystarczy jeden bajt. Polecam jednak stosowanie tych funkcji, poniewaû przy jeszcze nowszych koôciach moûe to byê konieczne (przy zaîoûeniu, ûe bëdâ jakieô "nowsze koôci" -- miejmy nadziejë, ûe Escom nas nie zawiedzie). ULONG GetAPen( struct RastPort *rp ); ULONG GetBPen( struct RastPort *rp ); Poniewaû nie wszystkie Amigi majâ powyûsze funkcje, naleûy sprawdzaê wersjë biblioteki (byîo to przerabiane w pierwszej czëôci), moûesz to równieû zobaczyê w listingu 9.: funkcje dajKolorA() i dajKolorB(). Jeûeli masz inkludy z systemu starszego niû 3.0, wystâpiâ problemy ze skompilowaniem tego listingu, poniewaû kompilator stwierdzi, ûe nie zadeklarowano niektórych funkcji. Sugerujë wiëc posiadaczom starszych inkludów zmodyfikowaê nieco program, usuwajâc wywoîania nieznanych kompilatorowi funkcji, a nastëpnie poszukaê nowszych plików nagîówkowych. Tak samo ma sië sprawa z polem "DrawMode", w którym odnotowany jest sposób (tryb) rysowania po oknie. Do jego zmiany sîuûy funkcja: void SetDrMd( struct RastPort *rp, unsigned long drawMode ); Do jego odczytania zaô uûywamy: ULONG GetDrMd( struct RastPort *rp ); Pojawiîa sië ona wraz z opisanymi wczeôniej funkcjami GetAPen() i GetBPen() -- w wypadku starszych systemów naleûy po prostu odczytaê pole RastPortu "DrawMode". Sâ zdefiniowane nastëpujâce tryby rysowania: JAM1 Tylko kolor atramentu jest umieszczany na RastPorcie. JAM2 Zarówno kolory atramentu, jak i tîa sâ umieszczane na RastPorcie. Tryb ten moûna odróûniê od JAM1 tylko w wypadku, gdy na RastPorcie umieszczane sâ napisy lub rysunki (o tym póúniej). COMPLEMENT Jest wykonywana róûnica symetryczna (XOR) obecnej zawartoôci RastPortu i tego, co ma byê narysowane. INVERSVID Wykonywana jest inwersja kolorów. Powyûsze tryby moûna swobodnie mieszaê ze sobâ, jednak niektóre kombinacje nie majâ sensu. Podejrzewam, ûe znaczenie poszczególnych trybów nie jest jeszcze zrozumiaîe, myôlë jednak, ûe sië to nieco przejaôni po zapoznaniu sië z dziaîaniem przykîadu. Do testowania sugerujë uûyê rysowania napisów, poniewaû tylko w tym wypadku rysowany jest kolor tîa, co pozwala odróûniê tryb JAM1 od JAM2. Proponujemy teraz zajrzeê do przykîadu: listing 9. Przykîad ten to demonstracja uûycia najprostszych funkcji graficznych systemu operacyjnego. Przy uûyciu odpowiednich klawiszy (bâdú klikajâc jednokrotnie na gadûecie zamykania okna) moûna sië przeîâczaê pomiëdzy róûnymi trybami pracy programu, takimi jak: rysowanie elips, punktów, zmiana kolorów itp. Rodzaj trybu, w jakim program znajduje sië w danym momencie, jest wyôwietlany na listwie tytuîowej okna. Rysuje sië za pomocâ myszy, w sposób czësto niezbyt elegancki (moûna np. rysowaê po listwie tytuîowej) i nieintuicyjny (nie jest tak od razu oczywiste, co w danym trybie robi przycisk lewy, a co prawy), ale ma to byê tylko przykîad, a nie jakiô uûyteczny program. Gdyby chcieê zrobiê to elegancko, to naleûaîoby skorzystaê z gadûetów, a na razie nie umiemy z nich korzystaê. Szczegóîowy opis listingu zamieszczony zostanie w nastëpnym odcinku kursu. Oto najczëôciej powtarzajâce sië w listach do mnie pytania. 1. Pytacie jak kompilowaê listingi. W kompilatorze SAS/C 6.x robi sië to z Shella piszâc "SC nazwa_listingu.c LINK". Nie polecamy osobnego wywoîywania linkera (slink), gdyû jest to bardziej skomplikowane. 2. W czëôci 1, w listingu 3, w pëtli "for" znajduje sië instrukcja "licznik--". Powinno byê oczywiôcie "licznik- -" (sîownie: licznik minus minus). 3. W czëôci 3, w listingu 5, zmienna "IntuitionBase" jest zmiennâ lokalnâ. Kompilator SAS/C skompiluje ten przykîad bez zarzutu, ale chyba wszystkie inne kompilatory sië "udîawiâ" - zmienna ta powinna byê globalna.