Podstawy Programowania Wykład czternasty: Grafika (modu ł Graph) cz ęść pierwsza
1. Wstęp Współczesne karty graficzne pozwalaj ą na tworzenie przestrzennej, realistycznej grafiki komputerowej. Niestety język Pascal, a konkretniej jego odmiana stwo- rzona przez firm ę Borland i udostępniona w postaci pakietu Turbo Pascal, nie pozwala na obsług ę zaawansowanych funkcji takich kart. Dostarczany wraz z tym środowiskiem modu ł graph pozwala obsługiwa ć karty graficzne w trybie zgodności ze standardem VGA udostępniając kilka trybów graficznych o względnie małej rozdzielczości (maksimum 1024x768 pikseli) i liczbie kolorów (maksimum 256) 1. Istnieje możliwo ść dostępu do trybów graficznych o wyższych rozdzielczościach i większej liczbie kolorów, ale wymaga ona użycia przerwa ń BIOS i nie będzie ona tu opisywana 2. Pomimo skromnych możliwości modu ł graph może by ć przydatny do uzyskania kilku ciekawych efektów graficznych i do zwiększenia atrakcyjności wizualnej napisanych w języku Pascal programów. 2. Ogólny opis modułu graph Pomimo, że możliwości graficzne, jakie oferuje modu ł graph ze współczesnego punktu widzenia s ą dosy ć skromne, to jego rozmiary s ą dosy ć znaczne. Elementy w nim zgromadzone możemy podzieli ć na cztery kategorie: związane z inicjalizacj ą trybu graficznego, związane z zarządzaniem trybem graficznym, związane z wyświetlaniem obrazu i związane z wyświetlaniem tekstu. Najwa- żniejsze z nich zostan ą omówione w następnych rozdziałach. 3. Elementy modułu graph związane z inicjalizacj ą trybu graficznego Inicjalizacja trybu graficznego (pierwsze włączenie) dokonywane jest za pomocą procedury InitGraph. Przyjmuje ona trzy argumenty wywołania. Pierwsze dwa s ą typu integer i musz ą by ć zmiennymi, ostatni jest typu string i może być zmienn ą lub ciągiem znaków. Pierwszy parametr wywołana określa sterownik, jaki ma zosta ć użyty do uruchomienia trybu graficznego. W module graph zostały zdefiniowane stałe pozwalające określi ć rodzaj sterownika. Oto niektóre z nich: Detect (0) procedura initgraph automatycznie 3 rozpozna kart ę graficz- n ą jaka zainstalowana jest w systemie, dobierze dla niej odpowiedni sterownik i wybierze najlepszy tryb wyświetlania, CGA (1) sterownik dla karty CGA, lub 1 Podane wartości maksymalne odnosz ą si ę do karty IBM851, rzadko obecnie spotykanej. 2 Tryby o wyższych rozdzielczościach nale żą do standardu VESA. Więcej o tych trybach i sposobach ich używania można przeczyta ć w książce autorstwa P.Metzgera i A.Jełowickiego pt Anatomia PC lub Tworzenie gier 2D i 3D w języku Turbo Pascal autorstwa Piotra Besty. 3 lub jak niektórzy wol ą automagicznie :-) 2
zgodnej z tym standardem, EGA (3) i EGA64 (4) sterowniki kart EGA, lub zgodnych z tym standardem, EGAMono - sterownik monochromatycznych kart EGA, lub zgodnych z tym standardem, HercMono (7) sterownik kart Hercules lub zgodnych z tym standardem, VGA (9) sterownik kart VGA lub zgodnych z tym standardem. Poniewa ż wszystkie współcześnie produkowane karty są zgodne ze standardem VGA najlepiej jest używa ć sterownika tej karty lub pozwoli ć procedurze initgraph automatycznie wykry ć rodzaj sterownika. Drugi parametr określa tryb graficzny jaki ma zosta ć użyty. Każdy z wymienionych wcześniej rodzajów kart graficznych oferuje kilka różnych trybów graficznych. Ze względów pragmatycznych zapoznamy si ę tylko z trybami oferowanymi przez karty VGA i zgodne z nimi. Karty te oferuj ą trzy tryby. Zostały zdefiniowane od- powiednie stałe w module graph, które ułatwiaj ą wybór tych trybów: VGALo (0) tryb wyświetlania o rozdzielczości 640x200 pikseli, 16 kolorach i 4 stronach, VGAMed (1) tryb o rozdzielczości 640x350 pikseli, 16 kolorach i 2 stronach, VGAHi (2) tryb o rozdzielczości 640x480 pikseli, 16 kolorach i jednej stronie. Piksel jest najmniejszym pojedynczym punktem, który można wyświetli ć na ekranie w trybie graficznym. Pierwsza liczba w oznaczeniu rozdzielczości oznacza liczb ę pikseli w poziomie, a druga w pionie. Strony s ą użyteczne w tworzeniu animacji. Jedna strona może by ć w danej chwili wyświetlana, podczas gdy na pozostałych tworzone s ą kolejne klatki animacji. Trzecim parametrem wywołania procedury initgraph jest ścieżka dostępu do katalogu, w którym znajduje si ę plik ze sterownikiem do karty graficznej (zazwyczaj pliki sterowników kart graficznych s ą umieszczone w katalogu BGI, który jest podkatalogiem katalogu, w którym znajduje si ę kompilator). Jeśli plik sterownika 4 znajduje si ę w katalogu bieżącym, to wystarczy jako ścieżk ę do- stępu poda ć pusty łańcuch znaków (''). Jeśli zmiennej, która będzie pierwszym argumentem wywołania przypiszemy warto ść stałej Detect, to procedura initgraph wywoła inn ą procedur ę o nazwie DetectGraph, celem wykrycia optymalnego sterownika i trybu graficznego. Procedura ta przyjmuje jako parametry wywołania dwie zmienne typu integer. W pierwszej zapisuje numer sterownika, w drugiej numer trybu graficznego. T ę procedur ę możemy również wywoła ć samodzielnie, przed wywołaniem initgraph, cho ć nie jest to często stosowane rozwiązanie. Jeśli po włączeniu trybu graficznego zachodzi koniecz- no ść chwilowego skorzystania z trybu tekstowego, to możemy dokonać przełączenia trybów za pomoc ą procedury RestoreCrtMode, która nie przyjmuje żadnych parametrów wywołania. Przywracany jest tryb tekstowy, który by ł używany przed włączeniem trybu graficznego. Aby powróci ć do trybu graficznego wywołujemy procedur ę SetGraphMode. Przyjmuje ona tylko jeden parametr wywołania i może nim by ć zmienna, wyrażenie lub wartość 4 W przypadku kart VGA i kompatybilnych plik sterownika nazywa si ę EGAVGA.BGI. 3
określająca numer trybu graficznego. Najczęściej stosuje si ę jedn ą z opisanych wyżej stałych. Jeśli chcemy skończy ć prac ę w trybie graficznym, to wywołujemy procedur ę CloseGraph. Nie wymaga ona żadnych parametrów wywołania. Typowa procedura inicjalizująca tryb graficzny może mie ć następując ą posta ć: procedure inicjalizuj; var sterownik,tryb,kod:integer; begin sterownik:=detect; initgraph(sterownik,tryb,'c:\tp\bgi'); kod:=graphresult; if kod <> grok then begin grapherrormsg(kod); halt(1); Działanie funkcji graphresult i grapherrormsg zostanie opisane w następnym rozdziale. Jeśli użyjemy tej procedury, to musimy zapewni ć, że sterownik karty graficznej znajdzie si ę w określonym przez trzeci parametr wywołania proce- dury katalogu. Jeżeli chcemy unikn ąć tego dosy ć niewygodnego rozwiązania możemy plik sterownika dołączy ć do pliku wykonywalnego naszego programu. Procedura inicjalizuj w tym wypadku powinna mie ć następując ą posta ć: procedure EGAVGAdriver; external; {$L EGAVGA.OBJ } procedure inicjalizuj; var grdriver,grmode:integer; begin grdriver:=detect; registerbgidriver(@egavgadriver); initgraph(grdriver,grmode,''); if graphresult<>grok then halt(1); 4
Przed definicj ą tej procedury powinna by ć zadeklarowana procedura sterow- nika karty. Jest to procedura zewnętrzna 5, zdefiniowana w innym pliku. O tym jak si ę nazywa ten plik informujemy kompilator za pomoc ą dyrektywy $L, tak jak to jest pokazane w kodzie źródłowym. W procedurze inicjalizuj przed wywo- łaniem initgraph wywołujemy procedur ę RegisterBGIDriver. Jako parametr 6 wywołania przyjmuje ona wskaźnik na procedur ę sterownika. Plik EGAVGA.OBJ uzyskujemy z pliku EGAVGA.BGI konwertując go za pomocą programu binobj dostarczanego wraz ze środowiskiem Turbo Pascala. W przypadku opisywanego pliku sterownika program ten wywołujemy z wiersza polece ń następująco: binobj egavga.bgi egavga.obj EGAVGAdriver 4. Elementy modułu graph związane z organizacj ą pracy w trybie graficznym Użyta w procedurze inicjalizującej funkcja GraphResult zwraca kod poprawno- ści wykonania operacji graficznej, przeprowadzonej bezpośrednio przed jej wywołaniem. Jeśli operacja ta zakończyła si ę pomyślnie, to zwracana jest warto ść 0 (zero), jeśli nie warto ść różna od zera. W module graph zostały zdefiniowane stałe odpowiadające wartościom sygnalizującym poszczególne błędy. Wartości zero odpowiada stała grok. Nazwy pozostałych stałych nie będ ą tu przytaczane. Jeśli chcemy uzyska ń komunikat (w języku angielskim) opisujący rodzaj błędu, to możemy wywoła ć procedur ę GraphErrorMsg. Przyjmuje ona jeden parametr wywołania będący wartości ą, wyrażeniem lub zmienn ą oznaczając ą kod błędu. Funkcja graphresult współpracuje między innymi z następującymi podprogramami modułu graph: bar, bar3d, clearviewport, closegraph, detectgraph, drawpoly, fillpoly, getgraphmode, imagesize, initgraph, pieslice, registerbgidriver, setallpalette, setfillpattern, setfillstyle, setgraphbufsize, setgraphmode, setlinestyle, settextjustify, settextstyle. Aby pozna ć nazw ę trybu graficznego w którym pracujemy, lub który nas interesuje, możemy posłuży ć si ę funkcj ą GetModeName. Jako parametr wywołania pobiera ona numer trybu, którego nazw ę chcemy uzyska ć, a zwraca warto ść typu string, zawierając ą nazw ę trybu. Tworząc obraz w trybie graficznym posługujemy si ę współrzędnymi. Układ współrzędnych we wszystkich trybach graficznych jest zorganizowany tak, jak pokazano to na rysunku: 5 O tym informuje słowo kluczowe external. 6 Inaczej adres procedury. Wskaźniki będ ą tematyk ą następnych wykładów. 5
0 maxx 0 maxy Aby pozna ć warto ść maksymalnej rzędnej i odciętej w bieżącym trybie graficz- nym użyjemy funkcji s ą typu GetMaxX i GetMaxY. Wartości zwracane przez te funkcje integer. Procedura GetModeRange zwraca numery trybów o najmniejszej i największej rozdzielczości dla danego sterownika. Przyjmuje ona trzy parametry wywołania. Pierwszym jest zmienna, wyrażenie lub warto ść typu integer będąca numerem sterownika. Jeśli chcemy pozna ć wymienione tryby dla bieżącego sterownika, to pierwszym parametrem wywołania getmoderange może by ć stała CurrentDriver (-128). Dwa następne parametry s ą zmiennymi typu integer. Pierwsza będzie zawierała numer trybu o najmniejszej rozdzielczo- ści, druga o największej. Jeśli chcemy operacje graficzne związane z rysowa- niem lub wyświetlaniem tekstu ograniczy ć tylko do pewnego wycinka po- wierzchni ekranu, to możemy zdefiniowa ć okno, które w języku angielskim na- zwane zostało viewport. Do tworzenia takiego okna służy procedura SetViewPort. Przyjmuje ona pi ęć argumentów wywołania. Pierwsze cztery są typu integer, ostatni typu boolean. Pierwsza para argumentów wywołania to współrzędne lewego, górnego rogu okna, druga to współrzędne prawego dolnego rogu okna. Ostatni parametr określa, czy umieszczane w oknie elementy mogą wystawa ć poza okno, czy nie. Jeśli ma on warto ść true, to rysowanie ograniczone jest tylko do obszaru okna. Zamiast bezpośrednio stosowa ć war- tości true i false możemy uży ć stałych ClipOn (true) i ClipOff (false). Do wyczyszczenia bieżącego okna używamy procedury ClearViewPort, która nie przyjmuje żadnych parametrów wywołania. Aby pozna ć parametry bieżącego okna możemy posłuży ć si ę procedur ą GetViewSettings. Przyjmuje ona tylko jeden parametr wywołania będący zmienn ą typu ViewPortType. ViewPortType = record x1,y1,x2,y2:integer; Clip: boolean; 6
Powyżej podana jest definicja tego typu w module graph. Pola x1, y1, x2, y2 są przeznaczone do przechowywania wartości współrzędnych odpowiednich rogów okna, natomiast pole Clip informuje, o tym, czy wyświetlanie jest ograniczone do obszaru okna, czy te ż nie. Do czyszczenia zawartości całego ekranu jest używana procedura ClearDevice, która nie przyjmuje żadnych parametrów wywołania. Kursor w trybie graficznym jest niewidoczny. Aby pozna ć jego położenie możemy uży ć funkcji GetX i GetY. Obie te funkcje zwracaj ą wartości typu integer i nie pobjeraj ą żadnych parametrów wywoł ania. Współrzędne kursora s ą liczone względem bieżącego okna. Aby umieści ć kursor w wybranym miejscu na ekranie wywołujemy procedur ę MoveTo. Przyjmuje ona dwa argumenty wywołania, które mog ą by ć zmienn ą, wyrażeniem lub wartością typu integer i które stanowi ą współrzędne nowego położenia kursora. Dzięki procedurze MoveRel mamy możliwo ść przemieszczenia kursora o pewien ustalony przez nas wektor, względem bieżącego jego położenia 7. Procedura ta równie ż przyjmuje dwa parametry typu integer, które s ą odpowiednio składową poziom ą i pionow ą wektora. Jeśli korzystamy z mechanizmu stron do tworzenia animacji, to procedura SetActivePage określa nam stron ę, na której będzie rysowana bieżąca klatka, a SetVisualPage, stron ę, która będzie wyświetlana. Obie procedury przyjmuj ą jeden parametr wywołania, który jest typu word i który jest numerem strony. Jeśli używamy sterowników do kart EGA, EGA64 lub VGA, to równocześnie na ekranie możemy wyświetli ć 16 kolorów. W module graph zdefiniowano stałe o odpowiednich nazwach dla każdego z nich (są dokładnie takie same, jak w module crt). Istnieje ponadto możliwo ść stworzenia swojej palety barw. Oferuje j ą procedura SetAllPalette. Przyjmuje ona za parametr wywołania zmienn ą typu PaletteType. Ten typ w module graph zosta ł zdefiniowany następująco: PaletteType = record Size : Byte; Colors : array[0..maxcolors] of ShortInt; gdzie stała MaxColors ma warto ść 15. Pole Size określa rozmiar palety kolorów, czyli ile elementów tablicy Colors będzie miało znaczące wartości. Warto ść elementu określa numer koloru. Oznacza to, że jeśli np. w elemencie tej tablicy o indeksie 0 (czarny) umieszcz ę warto ść 4 (zielony), to elementy, które dotychczas rysowałbym na czarno będ ę rysowa ł na zielono. Aby zmienić tylko jeden kolor w palecie możemy uży ć zamiast SetAllPalette procedury 7 Np. cztery piksele w prawo i dwa w dó ł. 7
SetPalette. Przyjmuje ona dwa parametry wywołania jeden typu word, drugi typu shortint i s ą to: numer koloru który ma by ć zmieniony i numer koloru na jaki ten kolor chcemy zmieni ć. Na bardziej elastyczn ą manipulacj ę kolorami palety pozwala nam procedura SetRGBPalette. Przyjmuje ona cztery argumenty wywołania, wszystkie typu integer. Pierwszym jest numer koloru w palecie, który ma by ć zmieniony, a następne trzy określaj ą, odpowiednio, składow ą czerwon ą, zielon ą i niebiesk ą tego koloru. Należy zauważy ć, że tylko wartości młodszych bajtów, trzech ostatnich parametrów s ą używane przez tę procedur ę. Funkcja GetMaxColor zwraca warto ść typu word określającą maksymalny numer koloru dla bieżącego trybu graficznego. Do określenia koloru, w jakim będ ą wyświetlane elementy obrazu służy procedura SetColor, natomiast do określenia koloru tła na jakim te elementy będ ą rysowane służy procedura SetBkColor. Obie one przyjmuj ą jeden parametr wywołania, który jest typu word. Funkcje GetColor i GetBkColor zwracaj ą wartości typu word będące numerami bieżących kolorów odpowiednio: rysowanych elementów i tła. Procedura SetWriteMode określa sposób rysowania obrazu, a właściwie sposób nakładania go na istniejące tło. Przyjmuje ona tylko jeden parametr wywołania typu integer. Najczęściej parametrem tym jest jedna z następujących stałych: NormalPut lub CopyPut (0) oznaczaj ą, że element będzie po prostu zastępowa ł fragment tła na którym będzie rysowany, XORPut (1) oznacza, że będzie wykonywana operacja xor dla każdego piksela rysowanego elementu i odpowiadającego mu piksela tła, na którym jest rysowany, OrPut (2) podobnie jak poprzednio, ale wykonywana jest operacja or, AndPut (3) wykonywana jest operacja and, NotPut każda warto ść piksela (kolor) jest negowana przed narysowaniem elementu. Do uzyskania numeru koloru piksela o wybranych współrzędnych możemy uży ć funkcji GetPixel. Przyjmuje ona dwa parametry wywołania, typu natomiast zwraca warto ść typu integer, które określaj ą rzędn ą i odcięt ą piksela, word, która jest numerem koloru piksela. Do pobrania bieżącej palety kolorów służy procedura GetPalette, która przyjmuje jako parametr wywołania jedn ą zmienn ą typu PaletteType. Rozmiar palety (liczb ę dostępnych kolorów) możemy pozna ć wywołując funkcję bezparametrow ą o nazwie GetPaletteSize. Zwraca on warto ść typu integer. Procedura SetLineStyle pozwala określi ć styl rysowanej linii. Procedura ta przyjmuje trzy argumenty wywołania, wszystkie typu word. Pierwszy z nich określa rodzaj stylu i może by ć następując ą sta łą: SolidLn (0) linia ciągła, DottedLn (1) linia kropkowana, CenterLn (2) linia symetrii (używana w rysunkach technicznych), DashedLn (3) linia kreskowana, UserBitLn (4) stała pozwalająca określi ć własny rodzaj linii. Jeśli jest ona podana jako pierwszy parametr wywołania SetLineStyle, to ma znaczenie warto ść drugiego parametru wywołania tej procedury. Jest to tzw. wzorzec bitowy linii (0 piksel 8
wygaszony, 1 piksel zapalony). Trzeci parametr określa grubo ść linii i najczęściej jest jedn ą z dwóch stałych: NormWidth (1) normalna szerokość linii, ThickWidth (3) linia pogrubiona. Niektóre z figur lub bry ł w trybie graficzny s ą rysowane wypełnione, inne można wypełni ć. Rodzaj wypełnienia można określi ć za pomoc ą procedury SetFillStyle, przyjmującej dwa parametry wywołania, oba typu word. Pierwszy z nich jest numerem wzorca, drugi numerem koloru wypełnienia. Istnieje możliwo ść zdefiniowania własnego wzorca wypełnienia, za pomoc ą procedury SetFillPattern. Przyjmuje ona dwa argumenty wywołania. Pierwszy jest typu FillPatternType, drugi jest typu word i okreś la kolor wzorca. Typ FillPatternType jest zdefiniowany w module graph następująco: FillPatternType = array [1..8] of Byte; Warto ść każdego elementu tej tablicy jest traktowana jako wzorzec bitowy zapisany w wierszu macierzy o rozmiarach 8x8. Jeśli rysowane na ekranie koło lub okrąg wydaj ą si ę nam eliptyczne, możemy t ę wad ę skorygowa ć używając funkcji SetAspectRatio, która ustala stosunek szerokości do wysokości ekranu. Przyjmuje ona dwa argumenty wywołania typu word określające nową szeroko ść i wysoko ść ekranu i zwraca równie ż warto ść typu word. Niestety dokumentacja elektroniczna nie podaje znaczenia tej wartości. Najczęściej jest ona w programach ignorowana. Do poznania stosunku szerokości i wysokości ekranu służy procedura GetAspectRatio, która pobiera jako parametry wywołania dwie zmienne typu word. Do tych zmiennych zostanie zapisana po wywołaniu procedury odpowiednio szeroko ść i wysoko ść ekranu. 5. Elementy modułu graph służące do tworzenia obrazu Modu ł graph dostarcza wielu podprogramów służących do tworzenia prostych obiektów graficznych (zwanych w grafice komputerowej prymitywami) oraz do tworzenia bardziej złożonych elementów obrazu. Najprostszym elementem obrazu komputerowego w trybie graficznym jest piksel. Możemy narysowa ć pojedynczy piksel, określając jego kolor za pomoc ą procedury PutPixel. Przyjmuje ona trzy parametry wywołania. Pierwsza para tych parametrów jest typu integer i określa współrzędne piksela (odpowiednio rzędn ą i odcięt ą), natomiast trzeci parametr jest typu word i określa kolor jaki piksel ma przyj ąć. Odcinek jest obiektem graficznym złożonym z punktów, czyli pikseli. Taki odcinek możemy narysowa ć za pomoc ą jednej z trzech procedury. Procedura Line przyjmuje cztery parametry typu integer, które s ą współrzędnymi punku początkowego i końcowego odcinka. Procedura LineTo rysuje odcinek od 9
punktu, w którym bieżąco znajduje si ę kursor, do punktu o podanych współrzędnych. Współrzędne te s ą przekazywane za pomoc ą dwóch parametrów wywołania typu integer. Na podobnej zasadzie działa procedura LineRel, ale jako parametry przyjmuje długo ść poziom ą i pionow ą wektora 8, który posłuży do wyliczenia punktu końcowego odcinka. Współrzędne tego punku s ą liczone względem bieżącego położenia kursora. Do narysowania prostokąta możemy si ę posłuży ć procedur ą rectangle, która przyjmuje cztery parametry typu integer określające położenie lewego górnego i prawego dolnego rogu rysowanego prostokąta. Jeśli chcemy, żeby ten prostokąt by ł wypełniony, to zamiast procedury rectangle użyjemy procedury bar wywoływanej w identyczny sposób (z dokładności ą do nazwy). Do rysowania okręgów na ekranie służy procedura Circle. Dwa pierwsze parametry wywołania tej procedury określaj ą współrzędne środka tego okręgu (s ą typu integer), natomiast ostatni parametr jest typu word i określa długo ść promienia okręgu. Fragment okręgu, czyli łuk możemy narysowa ć za pomoc ą procedury Arc. Przyjmuje ona pi ęć parametrów. Pierwsze dwa s ą typu integer i określają współrzędne środka okręgu, którego wycinek stanowi rysowany łuk. Ostatni parametr typu word określa promie ń tego okręgu, natomiast trzeci i czwarty parametr s ą typu word i określaj ą kąt początkowy, od którego jest rysowany łuk i kąt końcowy. Miara obu kątów jest wyrażona w stopniach. Jeśli chcemy, aby nasz łuk by ł wypełniony, to używamy procedury PieSlice 9 wywoływanej w ten sam sposób. Do rysowania elips lub ich fragmentów służy procedura Ellipse. Przyjmuje ona sze ść parametrów wywołania. Pierwsze dwa s ą typu integer, cztery kolejne s ą typu word. Dwa pierwsze to współrzędne środka elipsy, dwa kolejne to kąt początkowy i końcowy (jeśli ma by ć pełna elipsa, to musz ą to by ć odpowiednio: 0 i 360), a dwa kolejne, to długo ść półosi poziomej i pionowej elipsy. Jeśli rysujemy fragment elipsy, który ma by ć wypełniony, to używamy procedury Sector wywoływanej w identyczny sposób jak Ellipse. Całą i wypełnion ą elips ę możemy narysowa ć za pomoc ą procedury FillEllipse. Pobiera ona cztery argumenty wywołania. Dwa pierwsze s ą typu integer, dwa pozostałe typu word. Pierwsza para określa położenie środka elipsy, trzeci parametr określa długo ść półosi poziomej, czwarty długo ść półosi pionowej elipsy. Do narysowania dowolnej figury może posłuży ć nam procedura DrawPoly. Przyjmuje ona dwa parametry wywołania. Pierwszy, typu word, określa liczb ę charakterystycznych punktów rysowanej figury, natomiast drugi jest tablic ą rekordów typu PointType, które określaj ą współrzędne tych punktów. Typ PointType jest zdefiniowany następująco: 8 Podobnie jak ma to miejsce w przypadku MoveRel. 9 Dosłowne tłumaczenia z angielskiego: kawałek ciasta. Ten element graficzny służy najczęściej do tworzenia wykresów kołowych. 10
PointType = record X,Y:integer; Jeśli chcemy, aby nasza figura była wypełniona, zamiast DrawPoly użyjemy FillPoly. Sposób wywołania tej procedury nie zmienia si ę. Do narysowania prostopadłościanu możemy uży ć procedury Bar3d. Przyjmuje ona sześć parametrów wejściowych. Pierwsze dwie pary s ą współrzędnymi lewego górnego i prawego dolnego rogu przedniej ściany prostopadłościanu. Kolejny parametr, typu word określa głęboko ść prostopadłościanu, natomiast ostatni, typu boolean określa, czy ma by ć widoczny wierzchołek tego prostopadłościanu, czy te ż nie. Zamiast wartości true i false możemy uży ć, jako tego parametru, stałych TopOn (true) i TopOff (false). Czasem zachodzi konieczno ść skopiowania fragmentu obraz i umieszczenia go w innym miejscu. Aby skopiowa ć wybrany fragment obrazu należy uży ć procedury GetImage. Przyjmuje ona pi ęć parametrów wywołania. Pierwsze cztery s ą typu integer (może to by ć zmienna, warto ść lub wyrażenie). Pierwsza para jest współrzędnymi lewego, górnego rogu kopiowanego obszaru, druga prawego dolnego rogu (obszar ten jest prostokątny). Ostatni parametr może być 10 zdereferencjonowanym wskaźnikiem typu pointer. Ten wskaźnik zawiera adres dynamicznie przydzielonego obszaru pamięci, w którym będzie zapisany skopiowany fragment obrazu. Pami ęć t ą możemy przydzieli ć za pomocą procedury getmem. Dla tej procedury musimy określi ć ilo ść pamięci, któr ą ma przydzieli ć. Możemy to uczyni ć za pomoc ą funkcji ImageSize. Zwraca ona warto ść typu word, będąc ą liczb ą bajtów zajmowanych przez dany fragment obrazu, a pobiera cztery parametry wywołania typu integer, określające współrzędne lewego górnego i prawego dolnego rogu kopiowanego fragmentu obrazu. Wklejenia obrazu dokonujemy za pomoc ą procedury PutImage. Przyjmuje ona dwa parametry wywołania. Pierwsze dwa s ą typu integer i określaj ą współrzędne, w których ma znale źć si ę lewy, górny róg wklejanego obrazu, trzecim parametrem może by ć zdereferencjonowany wskaźnik zawierający adres pamięci, w której jest umieszczony wklejany obraz 11, natomiast jako ostatni parametr określa sposób umieszczenia obrazu na tle i powinna to by ć jedna ze stałych, które były opisywane wraz z procedurą SetWriteMode 12. 10 Temat wskaźników będzie poruszany na następnych wykładach. 11 Ta pami ęć pełni rol ę podobn ą do roli schowka w systemie MS Windows. 12 Prosz ę zauważy ć, że zastosowanie XORPut pozwoli w prosty sposób uzyska ć efekt operacji cof- nij (ang. undo). Wystarczy ponownie nałoży ć obraz, aby go usun ąć. 11
6. Elementy modułu graph związane z tekstem Niestety modu ł graph nie dysponuje tak wygodn ą w użyciu procedurą wypisywania tekstu, jak ą jest write. Dostępne s ą dwie procedury wykonujące, takie operacje, ale wypisujące tylko łańcuchy znaków. Jeśli chcemy wypisać warto ść innego typu, to musimy j ą skonwertowa ć na typ string. Pierwsz ą z tych procedur jest outtext, drug ą jest parametr wywołania typu współrzędnymi (typ outextxy. Pierwsza przyjmuje tylko jeden string, druga trzy, z czego dwa pierwsze są integer) punktu na ekranie, od którego będzie wypisywany tekst, natomiast trzeci jest zmienn ą typu string lub łańcuchem znaków. Aby określi ć sposób wypisywania tekstu na ekranie możemy posłuży ć si ę procedurą SetTextStyle. Pobiera ona trzy parametry wywołania typu word. Pierwszy parametr określa krój pisma, drugi kierunek, natomiast trzeci rozmiar znaków. Dostępnych jest kilka stałych zdefiniowanych w module graph, które mog ą być użyte jako warto ść pierwszego parametru. S ą to: DefaultFont (0) domyślny krój, TriplexFont (1) krój triplex (znaki s ą wygładzone), SmallFont (2) małe znaki, SansSerifFont (3) krój bezszeryfowy, GothicFont (4) krój gotycki. Jako warto ść drugiego parametru możemy zastosowa ć stałe: HorizDir (0) kierunek poziomy, VertDir (1) kierunek pionowy. Procedura SetTextJustify pozwala określi ć wyrównanie tekstu w pionie i poziomie. Przyjmuje ona dwa parametry typu word. Pierwszy z nich może by ć jedną z trzech stałych, określających sposób wyrównania tekstu w poziomie: LeftText (0) wyrównanie do strony lewej, CenterText (1) wyśrodkowanie tekstu, RightText (2) wyrównanie do strony prawej tekstu. Jako drugi parametr wywołania, określający wyrównanie tekstu w pionie, może zostać przekazana jedna z trzech następujących stałych: BottomText (0) wyrównanie w dó ł, CenterText (1) wyśrodkowanie i TopText (2) wyrównanie w gór ę. Jeśli chcemy pozna ć wymiary tekstu w pikselach, to możemy zastosowa ć dwie funkcje: TextHight która zwraca warto ść typu word, określając ą wysoko ść tekstu i TextWidth, która równie ż zwraca warto ść TextSettingsType = record Font:Word; Direction: Word; CharSize: Word; Horiz: Word; Vert: Word; 12
typu word, ale określając ą szeroko ść tekstu. Obie funkcje jako parametr wywołania przyjmuj ą łańcuch znaków lub zmienn ą typu string. Jeśli chcemy pozna ć parametry wyświetlania tekstu, to musimy uży ć procedury GetTextSettings. Przyjmuje ona tylko jeden parametr wywołania, będący zmienn ą typu TextSettingsType. Definicja typu, która jest umieszczona w module graph została podana w ramce na poprzedniej stronie. Pole Font zawiera informacje o kroju, pole Direction zawiera informacje o kierunku wypisywania, pole CharSize zawiera informacje o rozmiarze znaków, pole Horiz zawiera informacje o wyrównaniu pionowym tekstu, pole Vert o wyrównaniu poziomym. 13