XX.  

JEDNOTKA  GRAPH


Jednotka Graph implementuje prostředky pro ovládání grafických módů běžných videoadaptérů. Aby program mohl těchto prostředků použít, musí být splněny následující podmínky:

XX.1. 

Grafické chyby

Grafické chyby vznikají především při nesplnění některé z podmínek, uvedených v předchozím oddílu, nebo v důsledku neprovedené či neplatné inicializace grafiky (zavedení grafického ovladače do paměti a přepnutí adaptéru do požadovaného grafického módu. Jejich výskyt lze indikovat a ošetřit pomocí funkcí GraphResultGraphErrorMsg.

function GraphResult: Integer;

Vrací chybový kód poslední grafické operace. Hodnotou může být nula (úspěch) nebo celé záporné číslo (chyba):

  kód     popis chyby  
0 žádná chyba, operace byla úspěšná
–1 grafika není inicializována (dosud nebyl instalován ovladač)
–2 grafický adaptér nebyl zjištěn
–3 soubor ovladače nebyl nalezen
–4 soubor ovladače je vadný
–5 nedostatečná paměť pro načtení ovladače
–6 nedostatečná paměť při kreslení vyplněného obrazce
–7 nedostatečná paměť při vyplňování oblasti
–8 soubor fontu nebyl nalezen
–9 nedostatečná paměť pro načtení fontu
–10 chybné číslo grafického módu pro zvolený ovladač
–11 grafická chyba
–12 vstupně-výstupní grafická chyba
–13 soubor fontu je vadný
–14 chybné číslo fontu

Funkce GraphResult ovšem vnitřní chybový kód vynuluje, takže při opakovaném volání již vrací nulu. Pro vícenásobné testování téhož chybového kódu je tedy nutno použít pomocnou proměnnou, které bude jeho hodnota nejprve přiřazena.

Chybový kód generují pouze následující podprogramy jednotky (některé z nich zde nejsou popsány, uvedeny jsou pouze kvůli úplnosti výčtu):

Bar FloodFill RegisterBGIdriver SetLineStyle
Bar3DGetGraphMode RegisterBGIfontSetPalette
ClearViewPortImageSize SetAllPaletteSetTextJustify
CloseGraphInitGraph SetFillPatternSetTextStyle
DetectGraphInstallUserDriver SetFillStyle
DrawPolyInstallUserFont SetGraphBufSize
FillPolyPieSlice SetGraphMode

function GraphErrorMsg (Chyba: Integer): string;

Vrací řetězec, jehož hodnotou je stručný popis grafické chyby o kódu Chyba. Řetězec lze využít pro výpis chybového hlášení.

XX.2. 

Grafické módy zobrazení

Kreslicí podprogramy jednotky Graph mohou být volány teprve po zavedení ovladače grafických módů videoadaptéru do paměti a přepnutí videoadaptéru do grafického módu zobrazení. Jen v grafických módech jsou totiž jednotlivé pixely (elementární body) rastru zobrazovací plochy přímo přístupné (lze je zpracovávat samostatně). Podle typu adaptéru přitom lze zpravidla volit mezi několika podporovanými grafickými módy, lišícími se především rozlišovací schopností a počtem současně zobrazitelných barev.

procedure DetectGraph (var Gd, Gm: Integer);

Otestuje hardware počítače a vrací identifikační kód rozpoznaného typu videoadaptéru (parametr Gd) a jeho grafického módu s nejvyšším rozlišením (parametr Gm), které pak lze použít ve volání procedury InitGraph.

procedure InitGraph (var Gd, Gm: Integer; Cesta: string);

Zavede do operační paměti (na heap programu) grafický ovladač pro požadovaný typ videoadaptéru a nastaví požadovaný grafický mód zobrazení. V parametru Gd je očekáván identifikační kód typu adaptéru (tabulka 14), v parametru Gm identifikační kód grafického módu (tabulka 15) a v parametru Cesta systémová specifikace adresáře, v němž je uložen soubor ovladače (prázdný řetězec specifikuje aktuální pracovní adresář programu).

Při nastavení grafického módu je vymazána obrazovka a veškeré parametry zobrazení (aktuální kreslicí barva, souřadnice polohy grafického kurzoru atd.) jsou inicializovány implicitními hodnotami.

Tabulka 14: Podporované videoadaptéry
kód adaptér ovladač
CGA cga.bgi
MCGA cga.bgi
EGA egavga.bgi
EGA 64 egavga.bgi
EGA mono egavga.bgi
kód adaptér ovladač
IBM 8514 ibm8514.bgi
Hercules herc.bgi
ATT 400 att.bgi
VGA egavga.bgi
10  PC 3270 pc3270.bgi

Pokud je v parametru Gd předána nula, nastaví procedura InitGraph platné hodnoty proměnných GdGm automaticky, voláním procedury DetectGraph.

Není-li inicializace grafického systému úspěšná, vrací procedura InitGraph v parametru Gd číslo grafické chyby (tj. totéž záporné číslo, které lze získat následným voláním funkce GraphResult).

procedure SetGraphMode (Gm: Integer);

Nastaví požadovaný grafický mód videoadaptéru, jehož ovladač byl naposled instalován procedurou InitGraph. V parametru Gm je očekáván identifikační kód některého z podporovaných grafických módů adaptéru (podporované módy jsou označeny celými nezápornými čísly z jistého intervalu, jehož meze lze pro zadaný typ videoadaptéru získat voláním procedury GetModeRange).

Při nastavení grafického módu je vymazána obrazovka a veškeré parametry zobrazení (aktuální kreslicí barva, souřadnice polohy grafického kurzoru atd.) jsou inicializovány implicitními hodnotami.

Tabulka 15: Podporované grafické módy
adaptér mód rozlišení
CGA 0 320 × 200
1 320 × 200
2 320 × 200
3 320 × 200
4 640 × 200
MCGA 0 320 × 200
1 320 × 200
2 320 × 200
3 320 × 200
4 640 × 200
5 640 × 480
EGA 0 640 × 200
1 640 × 350
EGA 64 0 640 × 200
1 640 × 350
adaptér mód rozlišení
EGA mono 3 640 × 350
IBM 8514 0 640 × 480
1 1 024 × 768
HERCULES 0 720 × 348
ATT 400 0 320 × 200
1 320 × 200
2 320 × 200
3 320 × 200
4 640 × 200
5 640 × 400
VGA 0 640 × 200
1 640 × 350
2 640 × 480
PC 3270 0 720 × 350

Kromě hodnot horizontálního a vertikálního rozlišení (rozměrů rastru zobrazovací plochy) se grafické módy mohou lišit i hodnotami dalších parametrů, jako například počtem současně zobrazitelných barev.

procedure RestoreCrtMode;

Obnoví naposled použitý textový mód. Obnoveno je i případné nastavení výstupního okna, nikoli však obsah obrazovky (resp. videopaměti) ani pozice kurzoru — obrazovka je smazána a výchozí pozicí kurzoru je její levý horní roh.

Grafický ovladač zůstává i po obnovení textového módu instalován v operační paměti. Později lze kterýkoliv z jeho grafických módů aktivovat voláním procedury SetGraphMode.

procedure CloseGraph;

Stejně jako RestoreCrtMode obnoví naposled aktivní textový mód a navíc uvolní grafický ovladač z heapu programu.

procedure GraphDefaults;

Reinicializuje parametry zobrazení jejich implicitními hodnotami pro aktuální grafický mód. Grafický systém je reinicializován na počáteční stav, stejně jako procedurami InitGraph nebo SetGraphMode, výmaz obrazovky se však neprovádí (obsah videopaměti je zachován).

procedure GetModeRange (Gd: Integer; var Min, Max: Integer);

Vrací meze intervalu identifikačních čísel grafických módů, podporovaných pro zadaný typ videoadaptéru. Zadanou hodnotou parametru Gd je identifikační číslo typu adaptéru, vracenou hodnotou parametru Min resp. Max je dolní resp. horní mez uvedeného intervalu.

Například pro Gd = 9 (adaptér VGA) jsou vráceny hodnoty Min = 0 a Max = 2, takže pro adaptér VGA jsou podporovány grafické módy 0, 1 a 2.

function GetGraphMode: Integer;

Vrací identifikační číslo aktuálního (v daném okamžiku aktivního) grafického módu.

function GetMaxMode: Integer;

Vrací největší identifikační číslo grafického módu, platné pro aktuální typ adaptéru (definovaný posledním voláním procedury InitGraph).

function GetDriverName: string;

Vrací jméno aktuálního ovladače (zavedeného posledním voláním procedury InitGraph), tj. standardní jméno příslušného bgi-souboru (bez přípony, například 'EGAVGA').

function GetModeName (Gm: Integer): string;

Vrací jméno zadaného grafického módu aktuálního typu adaptéru (definovaného posledním voláním procedury InitGraph). Očekávanou hodnotou parametru Gm je identifikační číslo grafického módu. Například pro adaptér VGA a Gm = 2 je vrácen řetězec '640 x 480 VGA'.


PŘÍKLAD: Přepínání mezi textovým a grafickým módem videoadaptéru demonstruje následující program.

{======================================================================}
program Text_a_grafika;
{======================================================================}

 uses Crt, Graph;
 var  Gd, Gm: Integer;               { číslo grafického driveru a módu }

begin { program }
 Window(5, 10, 25, 15);              { inicializace textového okna     }
 TextColor(4);
 TextBackGround(3);
 ClrScr;
 WriteLn('TEXTOVÝ MÓD');
 ReadLn;                             { čekání na stisk klávesy ENTER   }
 Gd := 0;                            { detekce a inicializace grafiky  }
 InitGraph(Gd, Gm, '');
 OutText('GRAFIKA: driver ');        { výpis informace o aktuálním     }
 OutText(GetDriverName);             { grafickém driveru a módu        }
 OutText(', mód ');
 OutText(GetModeName(Gm));
 ReadLn;                             { čekání na stisk klávesy ENTER   }
 RestoreCrtMode;                     { obnovení textového režimu       }
 WriteLn('VYHNÁN Z OKNA');           { kurzor vlevo nahoře             }
 ReadLn;                             { čekání na stisk klávesy ENTER   }
 GotoXY(1, 1);                       { kurzor zpět v okně              }
 WriteLn('A V OKNĚ');
 ReadLn;                             { čekání na stisk klávesy ENTER   }
 SetGraphMode(Gm);                   { obnovení grafického módu        }
 OutText('ZNOVU GRAFIKA');
 ReadLn;                             { čekání na stisk klávesy ENTER   }
 CloseGraph                          { obnovení textového režimu       }
end.                                 { a uvolnění grafického ovladače  }

XX.3. 

Výstupní okna

Podobně jako v textových lze i v grafických módech zobrazení definovat výstupní okno — obdélníkový výřez zobrazovací plochy, jehož levý horní roh je pak počátkem soustavy relativních souřadnic. V grafických módech však výstup (kreslený prvek) nemusí být hranicí okna omezen. Souřadnice rostou zleva doprava resp. shora dolů od nuly. Implicitním oknem (je nastavováno jednak při inicializaci všech parametrů grafického systému, tj. při volání procedury InitGraph, SetGraphMode či GraphDefaults, jednak při inicializaci pracovní plochy procedurou ClearDevice) je celá zobrazovací plocha.

procedure SetViewPort (Xl, Yh, Xp, Yd: Integer; Orez: Boolean);

Definuje nové výstupní okno. Parametry XlYh resp. XpYd určují horizontální a vertikální absolutní souřadnice jeho levého horního resp. pravého dolního rohu (tedy souřadnici levého, horního, pravého a dolního okraje okna). Platné souřadnice musí náležet bodům uvnitř zobrazovací plochy a musí vyhovovat nerovnostem Xl <= XpYh <= Yd. Hodnota parametru Orez stanoví, zda má (True) či nemá (False) být grafický výstup hranicí okna ořezáván.

Při aktivním ořezávání nejsou zobrazovány (barveny) ty části kreslených prvků, které leží vně hranice okna — zobrazen je pouze průnik prvku s plochou okna. Ořezávání se však netýká polohy grafického kurzoru. Pokud je například kreslena úsečka od aktuální pozice grafického kurzoru do bodu vně hranice okna, není sice příslušná její část zobrazena, nová poloha kurzoru však odpovídá zadanému koncovému bodu.

Kromě případného ořezávání je založením okna definován nový počátek soustavy relativních souřadnic, do nějž je také přesunut (neviditelný) grafický kurzor. Obsah zobrazovací plochy založením okna ovlivněn není (výmaz se neprovádí).

type ViewPortType = record
                     X1, Y1, X2, Y2 : Integer;
                     Clip           : Boolean
                    end;

Datový typ ViewPortType se používá pro parametr procedury GetViewSettings, v němž jsou vraceny údaje o aktuálním stavu výstupního okna. Položky X1Y1 resp. X2Y2 pak obsahují horizontální a vertikální absolutní souřadnici levého horního resp. pravého dolního rohu okna a položka Clip hodnotu příznaku ořezávání True (provádí se) nebo False (neprovádí se).

procedure GetViewSettings (var Info: ViewPortType);

V parametru Info vrací údaje o aktuálním stavu výstupního okna. Typ ViewPortType je popsán výše.

procedure ClearViewPort;

Smaže obsah okna (vyplní jeho plochu aktuální barvou pozadí, tj. vynuluje hodnoty příslušných pixelů ve videopaměti) a umístí grafický kurzor do jeho levého horního rohu. Okolí okna není výmazem jeho obsahu ovlivněno.

procedure ClearDevice;

Smaže obsah celé obrazovky barvou pozadí (vynuluje hodnoty všech pixelů ve videopaměti) a umístí grafický kurzor do levého horního rohu aktuálního výstupního okna.

XX.4. 

Grafický kurzor

Grafický kurzor má podobnou funkci jako kurzor textový (některé kreslicí podprogramy zahajují kresbu zadaného prvku na pozici kurzoru), není však zobrazován a může se nacházet i mimo výstupní okno a dokonce i mimo zobrazovací plochu. Platný rozsah relativních souřadnic polohy kurzoru v okně je omezen pouze rozsahem hodnot typu Integer.

procedure MoveTo (X, Y: Integer);

Přesune grafický kurzor na pozici, definovanou horizontální (X) a vertikální (Y) souřadnicí vůči počátku souřadné soustavy (levému hornímu rohu aktuálního okna). Platnými souřadnicemi jsou všechny hodnoty typu Integer.

procedure MoveRel (dX, dY: Integer);

Přesune grafický kurzor na pozici, definovanou přírustky horizontální (dX) a vertikální (dY) souřadnice vůči pozici aktuální — přesune kurzor o dX pixelů vpravo a o dY pixelů dolů. Platnými hodnotami přírustků jsou všechny (i záporné) hodnoty typu Integer.

function GetMaxX: Integer;
function GetMaxY: Integer;

Funkce GetMaxX resp. GetMaxY poskytne absolutní souřadnici pravého resp. dolního okraje zobrazovací plochy (závislou na aktuálním grafickém módu).

function GetX: Integer;
function GetY: Integer;

Funkce GetX resp. GetY vrací horizontální resp. vertikální souřadnici aktuální pozice grafického kurzoru vůči počátku (levému hornímu rohu okna).

XX.5. 

Barvy

Celkový počet zobrazitelných barev je dán typem videoadaptéru, kterým je počítač vybaven. Adaptéry CGA například disponují ve čtyřech základních grafických módech zobrazení čtyřmi barevnými paletami po čtyřech pevně daných barvách. Aktivní je vždy jen jedna paleta, daná volbou odpovídajícího módu. Adaptéry EGA mohou zobrazit celkem 64 pevných barev, z nich je však současně zobrazitelných pouze zvolených 16. Na adaptérech VGA je barva „namíchána“ ze tří barev základních (složkových) — červené, zelené a modré. Jejich podíly ve výsledné barvě (tzv. intenzity) jsou definovány šestibitovými hodnotami, takže celkový počet realizovatelných barev je 218, tj. 262 144. V každém okamžiku však může být definováno (namícháno) pouze 256 barev a z nich je v podporovaných grafických módech VGA opět současně zobrazitelných pouze 16 vybraných. Omezení počtu současně zobrazitelných barev je dáno technickými prostředky adaptéru a paměťovými nároky na uložení barvy pixelu ve videopaměti. Má-li být současně zobrazitelných 16 barev, lze je oindexovat čísly 0 až 15 a do videopaměti ukládat tyto indexy. Pro uložení barvy každého pixelu pak postačí čtyři bity (půl bytu).

K popisu funkce prostředků, implementovaných jednotkou Graph pro ovládání barev, je třeba uvést alespoň základní údaje o funkčních principech videoadaptérů EGA a VGA (zpracováním barev na ostatních podporovaných typech adaptérů se zde zabývat nebudeme).

Adaptér EGA   EGA generuje pro řízení barvy pixelu na monitoru šest signálů, po dvou na každou ze základních barev — červenou, zelenou a modrou. Celkem je tedy realizovatelných 64 (26) barev, jejichž hodnoty jsou reprezentovány celými čísly 0 až 63. Součástí adaptéru je 16 registrů, do nichž je možno uložit hodnoty šestnácti aktuálně používaných barev, tzv. paletu. Do videopaměti není pak zapisována přímo barva pixelu (šestibitové celé číslo z intervalu <0, 63>), nýbrž index příslušného registru palety (čtyřbitové celé číslo z intervalu <0, 15>), v němž je použitá barva uložena. Při barvení pixelu na monitoru tedy adaptér získá ve videopaměti index registru barvy pixelu, jehož šest bitů již přímo určuje hodnoty barevných signálů.

Obrázek 78: Registr palety EGA

Struktura registru palety je znázorněna na obrázku 78. Trojice nižších bitů určuje hodnoty primárních signálů R (red — červená), G (green — zelená) a B (blue — modrá) a trojice vyšších bitů hodnoty sekundárních signálů r, gb. Hodnoty i sekundárních signálů přispívají k celkové intenzitě příslušné barevné složky poloviční měrou než hodnoty I signálů primárních. Každá ze základních složek proto může být ve výsledné barvě zastoupena některou ze čtyř možných intenzit — nulovou (Ii = 00), nízkou (třetinovou, Ii = 01), normální (dvoutřetinovou, Ii = 10) či plnou (Ii = 11).

Změna hodnoty barvy v některém z registrů palety se vizuálně projeví okamžitou změnou barvy všech odpovídajících pixelů zobrazovací plochy (hodnoty pixelů ve videopaměti přitom zůstávají stejné), čehož lze využít například pro animaci.

Adaptér VGA   VGA generuje pro intenzitu každé základní barvy jediný signál (celkem tedy tři), jehož hodnota však není digitální, nýbrž analogová — každý z těchto tří signálů (intenzita každé ze tří složek barvy) může nabývat některé z 64 možných hodnot — lze ji vyjádřit šestibitovým celým číslem z intervalu <0, 63>. Celkem je tedy realizovatelných 262 144 (218) vzájemně různých barev.

Součástí videoadaptéru jsou jsou dvě palety — paleta (kompatibilní s) EGA, tvořená šestnácti osmibitovými registry, a paleta VGA, která obsahuje 256 registrů po osmnácti bitech (šest na každou ze tří složek barvy). Standardním ovladačem egavga.bgi jsou podporovány pouze ty grafické módy adaptéru VGA, které jsou barevně kompatibilní s módy adaptéru EGA. Barva pixelu je do videopaměti ukládána opět jako čtveřice bitů a je interpretována jako odkaz na jeden ze šestnácti registrů palety EGA. Hodnota, kterou tento registr obsahuje, však neurčuje barvu pixelu přímo, nýbrž představuje další odkaz na některý z registrů palety VGA. Teprve hodnota tohoto registru definuje intenzity složek barvy.


POZNÁMKA: Mechanismus výpočtu barvy z hodnoty pixelu ve videopaměti je ve skutečnosti ještě poněkud složitější. Z hodnoty registru palety EGA je použito pro vyjádření odkazu na registr barvy v paletě VGA pouze nižších šest bitů. Zbývající dva jsou získány odjinud, přičemž mají standardně nulovou hodnotu. Uvedenými šesti bity je tedy mapováno pouze (prvních) 64 registrů barev, ostatní jsou bez přímého programování videoadaptéru nepřístupné. Z tohoto pohledu nemá smysl nastavovat hodnotu registrů palety EGA na číslo větší než 63 ani definovat barvy v jiných registrech palety VGA, než v prvních 64 (bez zajištění přístupu naprogramováním videoadaptéru).

Obrázek 79: Registr palety VGA

Struktura registru barvy palety VGA je znázorněna na obrázku 79. Nejnižší šestice bitů určuje intenzitu modré, střední šestice intenzitu zelené a nejvyšší šestice intenzitu červené složky barvy.

procedure SetColor (Index: Word);

Vybere barvu pro kreslení čar. V parametru Index je očekáváno číslo, které bude používáno jako hodnota pixelů kreslené čáry při zápisu do videopaměti — celé číslo z intervalu od nuly do počtu současně zobrazitelných barev, zmenšeného o jedna (například <0, 15> v šestnáctibarevných grafických módech).

Platný je pouze nižší byte parametru a z něj se podle počtu současně zobrazitelných barev použije při zápisu do videopaměti jen odpovídající počet nejnižších bitů. Například pro hodnotu 280 parametru bude hodnotou kreslicí barvy číslo 24 (280 mod 256). Při šestnácti současně zobrazitelných barvách z něj však budou pro zápis do videopaměti použity pouze nejnižší čtyři bity — číslo 8 (24 mod 16). Příkaz SetColor (280) tedy má za těchto podmínek stejný efekt jako příkaz SetColor (8).


POZNÁMKA: Jednotka Graph implementuje pro reprezentaci (indexů) barev stejné celočíselné konstanty (s hodnotami 0 až 15), jako jednotka Crt (viz konstanty barev).

Implicitní (počáteční) kreslicí barva závisí na grafickém módu (v šestnáctibarevných módech má hodnotu 15).

function GetColor: Word;

Poskytne aktuální hodnotu barvy pro kreslení čar.

procedure SetBkColor (Index: Word);

Vybere barvu pozadí, tj. vizuální barvu, kterou budou obarveny pixely s hodnotou 0. Parametr Index určuje index registru v paletě EGA (musí být tedy menší než 16), jehož hodnota bude zkopírována do nultého registru palety. Pro Index = 0 je do nultého registru palety vložena nula, pro neplatnou hodnotu parametru nemá volání procedury žádný efekt.

Například příkazem SetBkColor (5) je do nultého registru palety zkopírována hodnota pátého registru palety — pixely s hodnotou nula (pozadí kresby) budou pak mít vizuálně stejnou barvu, jako pixely s hodnotou 5. Příkazem SetColor (0) je do nultého registru palety dosazena hodnota nula, jíž standardně odpovídá černá barva.

Implicitní (počáteční) barva pozadí má hodnotu nula.

function GetBkColor: Word;

Poskytne aktuální hodnotu barvy pozadí, tj. hodnotu parametru posledního platného volání procedury SetBkColor (resp. nulu).

function GetMaxColor: Word;

Vrací největší číslo, které může vyjadřovat barvu pixelu ve videopaměti (počet současně zobrazitelných barev minus jedna). Funkci lze použít pro zjištění maximální hodnoty, jejíž uvedení ve volání procedur SetColorSetBkColor má ještě smysl.

function GetPaletteSize: Integer;

Vrací využitelnou velikost (počet registrů) palety videoadaptéru podle použitého ovladače a grafického módu. Například v šestnáctibarevných módech ovladače adaptérů EGA a VGA je vrácena velikost palety EGA, tj. 16.

procedure SetPalette (Index: Word; Barva: ShortInt);

Do registru Index palety vloží hodnotu parametru Barva.

const MaxColors   = 15;
type  PaletteType = record
                     Size   : Byte;
                     Colors : array [0..MaxColors]
                              of ShortInt
                    end;

Typ PaletteType se používá pro komunikaci s níže popsanými procedurami, které pracují se souvislými bloky registrů palety. Položka Size obsahuje počet registrů v bloku a prvních Size prvků pole Colors jejich hodnoty.

procedure GetPalette (var Paleta: PaletteType);

Vrací aktuální hodnoty (všech) registrů palety.

procedure GetDefaultPalette (var Paleta: PaletteType);

Vrací implicitní hodnoty registrů palety pro nastavený grafický mód.

Tabulka 16: Implicitní paleta pro módy 640 × 350 EGA a 640 × 480 VGA
reg. hodnota barva
0 (000000) černá
1 (000001) modrá
2 (000010) zelená
3 (000011) azurová
4 (000100) červená
5 (000101) fialová
20 (010100) hnědá
7 (000111) světle šedá
reg. hodnota barva
56 (111000) tmavošedá
57 (111001) jasně modrá
10  58 (111010) jasně zelená
11  59 (111011) jasně azurová
12  60 (111100) jasně červená
13  61 (111101) jasně fialová
14  62 (111110) žlutá
15  63 (111111) bílá

procedure SetAllPalette (var Paleta);

Nahradí hodnoty několika prvních registrů palety EGA hodnotami zadanými. Hodnota prvního bytu netypového parametru Paleta je interpretována jako počet modifikovaných registrů (max. 16), jejichž nové hodnoty specifikují další byty parametru. Je-li však nejvyšší bit některého z těchto bytů roven jedné, je původní hodnota odpovídajícího registru zachována (registr je „vynechán“).

Jako skutečný parametr procedury SetAllPalette lze použít například proměnnou typu PaletteType. Počet modifikovaných registrů palety se pak zadává v položce Size a jejich nové hodnoty v příslušných prvcích pole Colors (prvkům, které přísluší „vynechávaným“ registrům, je třeba přiřadit hodnoty záporné).

Použití procedury SetAllPalette demonstruje následující fragment programu. Modifikovány jsou pouze hodnoty prvního a čtvrtého registru palety, původní hodnoty ostatních registrů jsou zachovány. Vizuálními hodnotami nových barev jsou na adaptéru EGA černá a bílá, na VGA jsou určeny teprve hodnotami registrů barev 0 a 63 palety VGA (standardně rovněž černá a bílá).

var P: PaletteType;
...
 with P do
  begin
   Size := 5;
   Colors [0] := -1;     { 11111111 - ponechat  }
   Colors [1] :=  0;     { 00000000 - černá EGA }
   Colors [2] := -1;     { 11111111 - ponechat  }
   Colors [3] := -1;     { 11111111 - ponechat  }
   Colors [4] := 63      { 00111111 - bílá EGA  }
  end;
 SetAllPalette(P);
...
procedure SetRGBPalette (Index, R, G, B: Integer);

Definuje novou hodnotu osmnáctibitového registru barvy palety VGA, jehož index je zadán parametrem Index. Výsledná barva je namíchána ze základních složek o intenzitách R (intenzita červené), G (intenzita zelené) a B (intenzita modré). Významných je pouze nejnižších šest bitů každé z intenzit, což odpovídá hodnotám z intervalu <0, 63>.

Implicitní hodnoty prvních šedesáti čtyř registrů barev palety VGA jsou nastaveny tak, aby vizuální barvy odpovídaly barvám adaptéru EGA.

procedure GetRGBPalette (Index: Byte; var R, G, B: Byte);

Jednotka Graph neposkytuje prostředky pro čtení hodnot registrů palety barev VGA. Pokud se taková potřeba vyskytne, lze zavolat odpovídající rutinu BIOSu operačního systému například takto (v klauzuli uses je pak nutno deklarovat použití jednotky Dos):

procedure GetRGBPalette (Index: Byte; var R, G, B: Byte);
{-------------------------------------------------------}
{ Čte obsah registru Index palety VGA a vrací intenzity }
{ složek barvy v parametrech R, G a B.                  }

 var Reg: Registers;

begin { GetRGBPalette }
 with Reg do
  begin
   AH := $10;                    { číslo služby         }
   AL := $15;                    { číslo funkce služby  }
   BX := Index;                  { registr barvy        }
   Intr($10, Reg);               { volání přerušení $10 }
   R := DH;                      { červená              }
   G := CH;                      { zelená               }
   B := CL                       { modrá                }
  end
end; { GetRGBPalette }

XX.6. 

Úsečky

Při kresbě úseček a úsečkových obrazců je akceptována aktuální hodnota barvy pro kreslení čar (procedura SetColor), stylu kreslení čar (SetLineStyle) a módu zápisu pixelů čar do videopaměti (SetWriteMode). Jednoduché úsečky lze generovat procedurami Line, LineToLineRel, pravoúhelníky procedurou Rectangle a obecné lomené čáry procedurou DrawPoly.

procedure SetLineStyle (Druh, Vzorek, Tloustka: Word);

Definuje nový styl čar, který se uplatní při kreslení úseček a částečně i při kreslení oblouků. Atributy stylu jsou druh, vzorek a tloušťka čáry.

Požadovaný druh čáry je definován celočíselnou hodnotou parametru Druh. Použitelné jsou čtyři druhy s pevným (předdefinovaným) vzorkem a jeden druh se vzorkem uživatelským.

Tabulka 17: Druhy čar
druh vzorek
0 plná čára
1 tečkovaná čára
2 čerchovaná čára
druh vzorek
3 čárkovaná čára
4 uživatelský vzorek

Uživatelský vzorek se zadává šestnáctibitovou mapou v parametru Vzorek (pro jiný druh čáry než 4 je hodnota tohoto parametru ignorována). Hodnoty jednotlivých bitů mapy definují barvy šestnácti sousedních pixelů čáry — při kreslení jsou obarveny (aktuální barvou čar) pouze ty pixely čáry, kterým přísluší v mapě bity s hodnotou 1. Na obrázku je uveden příklad uživatelského vzorku čáry pro hodnotu mapy $5757 (0101011101010111b).

Obrázek 80: Příklad uživatelského vzorku čáry
 
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0
1
0
1
0
1
1
1
0
1
0
1
0
1
1
1
                               
 

Tloušťka čáry může být buď jeden nebo tři pixely. Platné hodnoty parametru Tloustka jsou 0 nebo 1 nebo 2 (tloušťka jeden pixel) a 3 (tloušťka tři pixely).

Implicitní styl čar definuje plnou čáru o tloušťce jeden pixel.

Volání procedury SetLineStyle s neplatnými hodnotami parametrů nemá na styl čar žádný vliv (původní styl zůstane zachován) a následující volání funkce GraphResult poskytne hodnotu –11.

type      LineSettingsType = record
                              LineStyle,
                              Pattern,
                              Thickness : Word
                             end;
procedure GetLineSettings (var Info: LineSettingsType);

Procedura GetLineSettings poskytne v parametru Info aktuální hodnoty atributů stylu čar. Položky LineStyle, PatternThickness záznamu LineSettingsType mají stejný význam jako parametry Druh, VzorekTloustka procedury SetLineStyle.

procedure SetWriteMode (Wm: Integer);

Definuje mód zápisu pixelů čar do videopaměti. Pro sudé hodnoty parametru Wm je nastaven mód MOV, pro liché mód XOR. V módu XOR je výsledný obraz získán kombinací čáry s původním obsahem obrazovky (na pozici pixelu do videopaměti je zapsána hodnota výrazu P xor Č, kde P je původní barva pixelu a Č je barva kreslené čáry), kdežto v módu MOV je původní obsah obrazovky prostě přepisován.

Užitečnost módu XOR spočívá především v tom, že opakovaná kresba stejné čáry (stejnou barvou) způsobí obnovení původního obsahu obrazovky. Toho lze využít například při animaci pohybu čáry.


POZNÁMKA: Společné body úseček obrazců, generovaných procedurami RectangleDrawPoly, jsou vykreslovány dvakrát (dílčí úsečky obrazce se v nich překrývají). Je-li nastaven mód zápisu XOR, budou dvojnásobně kreslené body v obrazci chybět.

procedure Line (X1, Y1, X2, Y2: Integer);

Nakreslí úsečku z bodu o souřadnicích X1Y1 do bodu o souřadnicích X2Y2 aktuální barvou, stylem a módem zápisu čar. Neovlivňuje polohu grafického kurzoru.

procedure LineTo (X, Y: Integer);

Nakreslí úsečku z bodu na pozici grafického kurzoru do bodu o souřadnicích XY aktuální barvou, stylem a módem zápisu čar. Grafický kurzor je přesunut na pozici XY.

procedure LineRel (dX, dY: Integer);

Pracuje stejně jako procedura LineTo, souřadnice koncového bodu úsečky dXdY jsou však vztaženy k počátečnímu bodu úsečky (aktuální pozici grafického kurzoru).

procedure Rectangle (X1, Y1, X2, Y2: Integer);

Nakreslí pravoúhelník se stranami rovnoběžnými s okraji obrazovky. Parametry X1Y1X2Y2 definují souřadnice jeho protilehlých vrcholů. Akceptuje aktuální barvu, styl a mód zápisu čar, neovlivňuje polohu grafického kurzoru.

procedure DrawPoly (PocetVrcholu: Word; var SeznamVrcholu);

Aktuální barvou, stylem a módem zápisu čar nakreslí lomenou čáru. Parametr PocetVrcholu specifikuje počet vrcholů čáry, netypový parametr SeznamVrcholu je interpretován jako pole o PocetVrcholu prvcích. Prvky pole jsou dvouslova, jejichž nižší resp. vyšší slovo obsahuje horizontální resp. vertikální souřadnici vrcholu. Pozice grafického kurzoru není kresbou ovlivněna.


PŘÍKLAD: Následující procedura vykreslí pravidelný N-úhelník (3 <= N <= 255) o poloměru R (v pixelech) a středem o souřadnicích SXSY.

{----------------------------------------------------------------------}
procedure Uhelnik (N: Byte; SX, SY: Integer; R: Word);
{----------------------------------------------------------------------}

 var Seznam : array[Byte] of record            { seznam vrcholů        }
                              X, Y: Integer
                             end;
     Alfa   : Real;                            { středový úhel         }
     I      : Byte;                            { index vrcholu         }

begin { Uhelnik }
 if N > 2 then                                 { minimálně trojúhelník }
  begin
   Alfa := 2 * Pi / N;                         { výpočet úhlu          }
   for I := 0 to N - 1 do                      { pro všechny vrcholy   }
    with Seznam[I] do
     begin
      X := SX + Round(R * Cos(I * Alfa));      { výpočet souřadnic     }
      Y := SY + Round(R * Sin(I * Alfa))
     end;
   Seznam[N] := Seznam[0];                     { uzavřený polygon      }
   DrawPoly(N + 1, Seznam)                     { kresba                }
  end
end; { Uhelnik }

XX.7. 

Oblouky

Implementovány jsou podprogramy pro generování kruhových a eliptických oblouků. Kresba je provedena aktuální barvou (procedura SetColor) a tloušťkou čar (SetLineStyle). Druh čar nemá na kresbu vliv. Mód zápisu má vliv pouze při současném nastavení tlustých čar. V tom případě ovšem dochází k nežádoucí fragmentaci čáry, neboť některé její pixely jsou kresleny vícenásobně.


POZNÁMKA: Při nastaveném uživatelském druhu čar s tloušťkou 3 je vykreslením oblouku nastavený vzorek čáry porušen (je třeba jej znovu nastavit voláním procedury SetLineStyle). Kresba oblouku by také neměla ovlivnit polohu grafického kurzoru, ve skutečnosti ji však mění, navíc nelze novou polohu zjistit funkcemi GetXGetY — ty vracejí polohu původní, jako by změněna nebyla.

procedure Circle (XS, YS: Integer; Polomer: Word);

Vykreslí kružnici o souřadnicích středu XSYS a poloměru Polomer. Kurzor je přesunut na pozici středu kružnice.

procedure Arc (XS, YS: Integer; PocUhel, KoncUhel, Polomer: Word);

Vykreslí kruhový oblouk. Parametry XSYSPolomer jsou souřadnice středu a poloměr bázové kružnice oblouku a parametr PocUhel resp. KoncUhel je kladně orientovaný úhel (ve stupních), který svírá spojnice středu bázové kružnice a počátečního resp. koncového bodu oblouku s horizontální souřadnou osou. Oblouk je vykreslen od počátečního do koncového bodu ve směru orientace úhlů (proti směru otáčení hodinových ručiček).

procedure Ellipse (XS, YS: Integer;
                   PocUhel, KoncUhel, PoloosaX, PoloosaY: Word);

Vykreslí eliptický oblouk. Pracuje obdobně jako procedura Arc, místo poloměru bázové kružnice se však zadávají velikosti horizontální a vertikální poloosy bázové elipsy oblouku.

type      ArcCoordsType = record
                           X, Y,
                           XStart, YStart,
                           XEnd, YEnd     : Integer
                          end;
procedure GetArcCoords (var Souradnice: ArcCoordsType);

Vrací souřadnice význačných bodů oblouku, vykresleného posledním voláním některé z procedur Circle, Arc, Ellipse, PieSlice, FillEllipse či Sector (poslední tři generují vyplňované obrazce). V položkách XY parametru Souradnice jsou vráceny souřadnice středu bázové kružnice resp. elipsy oblouku a v položkách XStartYStart resp. XEndYEnd souřadnice počátečního resp. koncového bodu oblouku.

procedure GetAspectRatio (var Xasp, Yasp: Word);
procedure SetAspectRatio (Xasp, Yasp: Word);

Procedura GetAspectRatio resp. SetAspectRatio vrací resp. nastaví rozlišovací poměr, používaný pro korekci vertikální deformace kreslených kružnic a kruhových oblouků (elipsy a eliptické oblouky korigovány nejsou).

K deformaci dochází při nesouhlasu poměru šířky a výšky rastru zobrazovací plochy v pixelech s poměrem šířky a výšky rastru ve vizuálních měrných jednotkách — standardně 4 : 3. Pokud je tedy nastaven rozlišovací poměr 1 : 1 (žádná korekce), budou například v grafickém módu 640 × 480 VGA kružnice vizuálně nezdeformované (neboť 640 : 480 = 4 : 3), kdežto například v grafickém módu 640 × 350 EGA budou vizuálně zdeformované (neboť 640 : 350 <> 4 : 3).

Při jiném rozlišovacím poměru než 1 : 1 jsou místo kružnic a kruhových oblouků kresleny elipsy a eliptické oblouky. Zvětšením poměru Xasp : Yasp lze dosáhnout prodloužení, zmenšením pak zkrácení vertikální poloosy náhradní elipsy. Velikost horizontální poloosy náhradní elipsy je vždy rovna velikosti poloměru původní kružnice.

Volbu optimálního rozlišovacího poměru lze uskutečnit následujícím způsobem (za předpokladu, že vizuální rozměry rastru zobrazovací plochy vyhovují základnímu poměru 4 : 3):

var Sirka, Vyska,
    Xasp, Yasp   : Word;
...
Sirka := GetMaxX + 1;                          { šířka rastru     }
Vyska := GetMaxY + 1;                          { výška rastru     }
Yasp  := 10000;                                { výpočet poměru   }
Xasp  := Round(4/3 * Vyska/Sirka * Yasp); 
SetAspectRatio(Xasp, Yasp);                    { nastavení poměru }
...

XX.8. 

Vyplňované obrazce

Jednotka Graph implementuje řadu procedur pro generování jednoduchých vyplněných obrazců. Vzhled použité výplně je třeba definovat předem, výběrem některého ze standardních vzorů (procelura SetFillStyle) nebo definicí uživatelského vzoru (procedura SetFillPattern). Obrysy obrazců (pokud existují) jsou vykreslovány aktuální barvou (procedura SetColor) a tloušťkou čar (SetLineStyle).


POZNÁMKA: Při nastavení jiného druhu čáry než plné nebo módu zápisu XOR dochází k různým poruchám v zobrazení obrysů. Podobně jako při kresbě oblouků je i při kreslení vyplněných obrazců ovlivňována poloha grafického kurzoru, opět bez možnosti indikace nové polohy funkcemi GetXGetY. Z uvedených důvodů je vhodné nepoužívat při kreslení vyplněných obrazců problémové atributy čar a polohu grafického kurzoru považovat po skončení kresby každého obrazce za nedefinovanou.

procedure SetFillStyle (Vzor, Barva: Word);

Vybere nový styl vyplňování obrazců. Hodnotou parametru Vzor je index jednoho z dvanácti standardních výplňových vzorů (viz tabulka), tj. celé číslo z intervalu <0, 11>. Parametr Barva určuje barvu pixelů, které tvoří popředí vzoru (například šrafy). Ostatní pixely vyplňované plochy (mezery mezi šrafami) jsou obarveny barvou pozadí (na pozici pixelu do videopaměti je zapsána nula).

Tabulka 18: Standardní vzory výplně obrazců
index vzorek
0 prázdný
1 plný
index vzorek
2 — 9 různé šrafy
10 a 11 řídké a husté tečky


POZNÁMKA: Při nastaveném prázdném vzoru je standardně celý vnitřek generovaného obrazce vyplněn barvou pozadí. Pokud je však generovaným obrazcem kruhová nebo eliptická výseč, výplň aplikována není (vykreslen je pouze obrys výseče).

Voláním procedury SetFillStyle s neplatnou hodnotou parametru Vzorek (větší než 11) se původní styl vyplňování nezmění. Funkce GraphResult pak vrací nenulovou hodnotu (–11).

Implicitní atributy stylu vyplňování jsou plný vzorek a poslední barva palety (závisí na grafickém módu).

type      FillSettingsType = record
                              Pattern, Color: Word
                             end;
procedure GetFillSettings (var Info: FillSettingsType);

Procedura GetFillSettings vrací aktuální hodnoty atributů stylu vyplňování — index vzoru (položka Pattern parametru) a barvu popředí vzoru (položka Color). Hodnota 12 položky Pattern indikuje uživatelský vzor.

type      FillPatternType = array [1..8] of Byte;
procedure SetFillPattern (Mapa: FillPatternType; Barva: Word);

Procedura SetFillPattern nastaví nový styl vyplňování, založený na uživatelském výplňovém vzoru. Vzor je definován bitovou mapou Mapa a barvou popředí Barva.

Parametr Mapa je maticí o rozměru 8 × 8 bitů (osm bytů po osmi bitech) a definuje čtvercový vzor výplně (dlaždici) o rozměru 8 × 8 pixelů. Řádky vzoru odpovídají bytům mapy v pořadí shora dolů a pixely řádek bitům příslušného bytu v pořadí zprava doleva (viz obrázek). Podle hodnoty 1 resp. 0 bitu mapy je příslušný pixel vyplňovaného obrazce obarven zadanou barvou popředí resp. barvou 0 (pozadí).

Obrázek 81: Příklad uživatelského vzorku výplně
 
76543210
Mapa[1]
0 0 1 0 0 0 0 0
0 1 1 1 0 0 1 0
1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0
0 0 1 1 1 1 1 0
0 0 1 1 1 1 1 0
0 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0
= $20
Mapa[2]= $72
Mapa[3]= $FE
Mapa[4]= $7E
Mapa[5]= $3E
Mapa[6]= $3E
Mapa[7]= $7E
Mapa[8]= $00
 

procedure GetFillPattern (var Mapa: FillPatternType);

Vrací bitovou mapu vzorku uživatelské výplně, definované posledním voláním procedury SetFillPattern. Pokud uživatelská výplň dosud definována nebyla (od poslední reinicializace atributů grafického systému), nastaví všechny bity parametru na hodnotu 1.

procedure Bar (X1, Y1, X2, Y2: Integer);

Vyplní pravoúhelník, definovaný souřadnicemi X1Y1X2Y2 protilehlých vrcholů (strany pravoúhelníka jsou rovnoběžné s okraji obrazovky). Obrys kreslen není a poloha grafického kurzoru je zachována.

procedure Bar3D (X1, Y1, X2, Y2: Integer; Hloubka: Word; Viko: Boolean);

Nakreslí obrys přední, pravé a volitelně i horní stěny kvádru a přední stěnu vyplní (používá se pro kreslení sloupcových diagramů). Parametry X1Y1X2Y2 jsou souřadnice protilehlých vrcholů přední stěny, parametr Hloubka udává šířku boční stěny (v pixelech) a hodnota parametru Viko rozhoduje o zobrazení (True) či nezobrazení (False) horní stěny. Grafický kurzor je přesunut do pravého horního rohu pravé stěny.

procedure PieSlice (XS, YS: Integer;
                    PocUhel, KoncUhel, Polomer: Word);

Vykreslí kruhovou výseč a vyplní ji. Parametry mají stejný význam jako při kreslení kruhového oblouku (procedura Arc) — XSYS jsou souřadnice středu bázové kružnice (vrcholu výseče), Polomer je její poloměr (délka ramen výseče) a PocUhelKoncUhel jsou kladně orientované úhly, které svírají ramena výseče s horizontální souřadnou osou. Grafický kurzor je přesunut na pozici XSYS.

Na pořadí úhlů tentokrát nezáleží, oblouk výseče je kreslen od konce ramene s menším úhlem ke konci ramene s větším úhlem vždy v kladném směru (proti směru hodinových ručiček). Nelze proto nakreslit výseč, jejíž oblouk by přecházel ze čtvrtého do prvního kvadrantu bázové kružnice (PocUhel > KoncUhel) — místo ní je nakreslen její doplněk.

procedure Sector (XS, YS: Integer; PocUhel, KoncUhel,
                  PoloosaX, PoloosaY: Word);

Vykreslí eliptickou výseč a vyplní ji. Pracuje stejně jako procedura PieSlice, místo poloměru bázové kružnice se však zadávají velikosti horizontální a vertikální poloosy bázové elipsy PoloosaXPoloosaY.

procedure FillEllipse (XS, YS: Integer; PoloosaX, PoloosaY: Word);

Vykreslí a vyplní elipsu (nebo kružnici). Parametry XSYS jsou souřadnice jejího středu a parametry PoloosaXPoloosaY velikosti její horizontální a vertikální poloosy. Grafický kurzor je přesunut na pozici XSYS.

procedure FillPoly (PocetVrcholu: Word; var SeznamVrcholu);

Vykreslí uzavřenou lomenou čáru a vyplní vnitřek vzniklé uzavřené oblasti (oblastí). Parametr PocetVrcholu specifikuje počet vrcholů čáry, netypový parametr SeznamVrcholu je interpretován jako pole o PocetVrcholu prvcích. Prvky pole jsou dvouslova, jejichž nižší resp. vyšší slovo obsahuje horizontální resp. vertikální souřadnici vrcholu. Pozice grafického kurzoru není kresbou ovlivněna.

Lomená čára, která tvoří obrys obrazce, je vykreslena stejným způsobem jako v proceduře DrawPoly, avšak její poslední vrchol je spojen s bodem prvním, takže je uzavřená automaticky.

procedure FloodFill (X, Y: Integer; Okraj: Word);

Vyplní obecnou spojitou oblast, uzavřenou hraniční barvou Okraj. Parametry XY jsou souřadnice libovolného vnitřního bodu oblasti (počátku vyplňování). Neovlivňuje polohu grafického kurzoru.


PŘÍKLAD: Následující program demonstruje vykreslení vyplněného uzavřeného polygonu procedurou FillPoly a dodatečné vyplnění jeho okolí procedurou FloodFill.

{======================================================================}
program Polygon;
{======================================================================}

 uses  Graph;

 const N      =  8;                    { počet vrcholů polygonu        }
       Obrys  = 15;                    { barva obrysu polygonu         }

 var   Gd, Gm : Integer;               { grafický driver a mód         }
       Seznam : array [0..N - 1] of    { seznam souřadnic vrcholů pol. }
                 record
                  X, Y : Integer
                 end;
       I      : 0..N;                  { index vrcholu                 }

begin { program }
 Gd := 9; Gm := 2;                     { 640 x 480 VGA                 }
 InitGraph(Gd, Gm, '');                { inicializace grafiky          }
 for I := 0 to N - 1 do                { naplnění seznamu souřadnicemi }
  with Seznam[I] do                    { vrcholů polygonu              }
   begin
    X := 40 + I * 80;
    if Odd(I) then Y := 100            { "cik-cak"                     }
              else Y := 380
   end;
 SetColor(Obrys);                      { barva čar                     }
 SetFillStyle(8, 14);                  { styl výplně polygonu          }
 FillPoly(N, Seznam);                  { kresba polygonu               }
 Readln;                               { čekání na stisk klávesy ENTER }
 SetFillStyle(11, 6);                  { styl výplně okolí polygonu    }
 FloodFill(280, 300, Obrys);           { vyplnění okolí bodu [280,300] }
 Readln;                               { čekání na stisk klávesy ENTER }
 CloseGraph                            { úklid a obnovení textového m. }
end. { program }

XX.9. 

Grafický text

Výstup textu na obrazovku realizují v grafických módech procedury OutTextOutTextXY. Vystupující text je grafickým prvkem, takže je spolu s ostatními grafickými prvky ořezáván hranicí výstupního okna (pokud je ořezávání povoleno). Volit lze druh písma (font), stupeň jeho velikosti, směr zápisu a relativní umístění vzniklého nápisu vůči počáteční poloze grafického kurzoru (zarovnání).

Zobrazení znaků vystupujícího textu je provedeno aktuální barvou čar, avšak styl čar ani mód zápisu pixelů čar do videopaměti na něj nemají vliv. Nová poloha grafického kurzoru závisí na všech uvedených parametrech. Nejpraktičtější je pokládat ji za nedefinovanou nebo prověřit v konkrétním případě chování kurzoru pokusem.

procedure SetTextStyle (Font, Smer, Stupen: Word);

Definuje nový styl písma. Atributy stylu jsou druh písma (font), směr zápisu a stupeň velikosti znaků. Zadávají se celočísenými hodnotami parametrů Font, SmerStupen.

Druh písma určuje grafické provedení jednotlivých znaků textu. Standardně je k dispozici jedenáct druhů písma, pro jejich rozlišení se používají čísla podle následující tabulky. Implicitní je písmo základní (0).

Tabulka 19: Druhy grafických písem
písmo soubor popis
0    základní písmo
1    trip.chr patkové písmo s trojitými tahy
2    litt.chr malé hranaté písmo s jednoduchými tahy
3    sans.chr bezpatkové písmo s dvojitými tahy
4    goth.chr gotické lomené písmo s trojitými tahy
5    scri.chr psané písmo (skript) s jednoduchými tahy
6    simp.chr bezpatkové písmo s jednoduchými tahy
7    tscr.chr kurzivní patkové písmo s trojitými tahy
8    lcom.chr patkové písmo s dvojitými tahy
9    euro.chr bezpatkové písmo s jednoduchými tahy
10    bold.chr tučné bezpatkové písmo s jednoduchým obrysem

Tvary jednotlivých znaků základního písma jsou definovány bitovými mapami o pevných rozměrech 8 × 8 bitů. Ostatní písma jsou vektorová (tahy jednotlivých znaků jsou tvořeny lomenými čarami, jejichž tloušťka — jediný pixel — je nezávislá na zvoleném stupni písma) a jejich definice jsou uloženy v samostatných souborech. Vykreslování znaků vektorových písem není tak rychlé jako vykreslování znaků písma základního, jejich zvětšování však nevede k nežádoucím deformacím.


POZNÁMKA: Definiční soubory použitých vektorových písem jsou hledány až za běhu programu, a to v jeho pracovním adresáři a v adresáři, ze kterého byl získán grafický ovladač (uvedeném ve volání procedury InitGraph). Standardně jsou umístěny v podadresáři bgi adresáře Turbo Pascalu.

Parametr Smer může nabývat pouze dvou hodnot, platných pro všechna písma — hodnota 0 definuje horizontální směr zápisu zleva doprava a hodnota 1 vertikální směr zápisu zdola nahoru. Pokud je použito základní písmo, smí mít parametr ještě hodnotu 2 — horizontální směr zápisu textu zleva doprava s ležatými znaky (otočenými o 90°). Implicitní směr zápisu je 0.


POZNÁMKA: Ostatní hodnoty (3 až 65 535) sice nemají vliv na hodnotu chybového kódu procedury (funkce GraphResult vrací nulu), mohou však způsobit různé poruchy v zobrazování textu nebo dokonce běhovou chybu programu.

Parametr Stupen určuje stupeň velikosti znaků písma. Nejmenší velikost odpovídá stupni 1. Maximální velikost znaků základního písma resp. ostatních písem určuje stupeň 31 resp. 10 (větší hodnoty parametru nejsou chybné, ale jsou brány modulo 32 resp. mají stejný efekt jako 10). Platná je i hodnota 0, která nastaví pro základní písmo stejnou velikost jako stupeň 1, pro vektorová písma pak uživatelskou velikost (definovanou procedurou SetUserCharSize). Implicitní stupeň je 1.

const DefaultFont   = 0;
      TriplexFont   = 1;
      SmallFont     = 2;
      SansSerifFont = 3;
      GothicFont    = 4;

      HorizDir      = 0;
      VertDir       = 1;

Frekventovaná písma a všeobecně použitelné směry zápisu jejich znaků lze kódovat také výše uvedenými konstantami jednotky Graph.

procedure SetUserCharSize (MultX, DivX, MultY, DivY: Word);

Definuje nové uživatelské rozměry znaků všech vektorových písem stupně 0 a pokud je některé z vektorových písem použito v aktuálním stylu, nastaví stupeň jeho velikosti na 0. Implicitní uživatelské rozměry znaků vektorových písem odpovídají pevným rozměrům znaků týchž písem stupně 4.

Nové uživatelské rozměry jsou definovány jako násobky implicitních uživatelských rozměrů — poměr MultX : DivX resp. MultY : DivY je požadovaným poměrem nové a implicitní uživatelské šířky resp. výšky každého znaku.

Například příkaz SetUserCharSize (2, 1, 2, 3) definuje uživatelské rozměry znaků vektorových písem tak, že jejich šířka bude dvojnásobkem šířky implicitní a výška dvěmi třetinami výšky implicitní.

function TextHeight (S: string): Word;
function TextWidth (S: string): Word;

Funkce TextHeight resp. TextWidth vrací výšku resp. šířku obrazu řetězce S (v pixelech), podle aktuálního nastavení stylu písma.


POZNÁMKA: Základní písmo je neproporcionání — šířka všech znaků je stejná (šířka i výška každého znaku je rovna osminásobku stupně písma, neboť bitová mapa každého znaku má rozměry 8 × 8 bodů). U vektorových písem jsou šířky jednotlivých znaků individuální.

procedure SetTextJustify (Horiz, Vert: Word);

Definuje zarovnávání vypisovaného textu vůči počáteční poloze grafického kurzoru. Povolené hodnoty obou parametrů Horiz (horizontální zarovnávání) a Vert (vertikální zarovnávání) jsou 0, 1 a 2. Odpovídá jim horizontální zarovnání textu vpravo od kurzoru (0), středem ke kurzoru (1) a vlevo od kurzoru (2) resp. vertikální zarovnání textu nad kurzor (0), středem ke kurzoru (1) a pod kurzor (2). Implicitně je vypisovaný text zarovnáván vpravo pod počáteční pozici grafického kurzoru (přiléhá k ní svým levým a horním okrajem).


POZNÁMKA: Pokud je v aktuálním stylu písma nastaveno základní písmo a  směr zápisu zdola nahoru, lze nastavit pouze dvě alternativy horizontálního zarovnávání — vlevo (0 nebo 2) a na střed (1).

Při chybné hodnotě některého z parametrů procedury SetTextJustify zůstane zachován původní způsob zarovnávání a funkce GraphResult indikuje chybu.

const RightText  = 0;
      CenterText = 1;
      LeftText   = 2;
      TopText    = 0;
      BottomText = 2;

Ke kódování horizontálního a vertikálního zarovnávání textu lze použít i výše uvedené konstanty jednotky Graph.

type      TextSettingsType = record
                              Font, Direction,
                              CharSize,
                              Horiz, Vert      : Word
                             end;
procedure GetTextSettings (var Info: TextSettingsType);

Vrací aktuální hodnoty atributů stylu písma a zarovnávání textu, nastavené procedurami SetTextStyleSetTextJustify — druh písma (položka Font parametru), směr zápisu znaků (Direction), stupeň velikosti (CharSize), horizontální zarovnávání (Horiz) a vertikální zarovnávání (Vert).

procedure OutText (S: string);
procedure OutTextXY (X, Y: Integer; S: string);

Procedury vypisují aktuální barvou čar, stylem písma a způsobem zarovnávání hodnotu řetězce S. Počáteční pozice grafického kurzoru je dána pro OutText jeho pozicí aktuální, pro OutTextXY pak hodnoto parametrů X (horizontální souřadnice) a Y (vertikální souřadnice). Konverze pro výpis hodnot jiných než řetězcových typů nejsou implementovány.


PŘÍKLAD: Následující program demonstruje možnosti zarovnávání grafického textu.

{======================================================================}
program JustifyDemo;
{======================================================================}

 uses  Crt, Graph;

 const H : array [0..2] of string[9]        { kontrolní nápisy         }
         = ('vpravo', 'uprostred', 'vlevo');
       V : array [0 .. 2] of string [9]
         = ('nahore', 'uprostred', 'dole');

 var   Gd, Gm : Integer;                    { driver a mód             }
       Smer,                                { směr zápisu              }
       Horiz,                               { vertikální zarovnávání   }
       Vert   : Word;                       { horizontální zarovnávání }
       Stisk  : Char;                       { stisknutá klávesa        }

begin { program }
 Gd := 0;                                   { detekce adaptéru         }
 InitGraph(Gd, Gm, '');                     { inicializace grafiky     }
 for Smer := 0 to 2 do                      { všemi směry zápisu       }
  begin
   SetTextStyle(0, Smer, 1);                { základní písmo           }
   for Horiz := 0 to 2 do                   { všechny způsoby horiz.   }
    for Vert := 0 to 2 do                   { a vert. zarovnávání      }
     begin
      SetTextJustify(Horiz, Vert);          { nastavení zarovnávání    }
      Line(GetMaxX div 2, 0,                { středový kříž            }
           GetMaxX div 2, GetMaxY);
      Line(0, GetMaxY div 2,
           GetMaxX, GetMaxY div 2);
      MoveTo(GetMaxX div 2, GetMaxY div 2); { kurzor na střed kříže    }
      OutText(H[Horiz] + ' ' + V[Vert]);    { kontrolní nápis          }
      Stisk := ReadKey;                     { čekání na stisk klávesy  }
      ClearViewPort                         { mazání obrazovky         }
     end
  end;
 CloseGraph                                 { úklid a obnova textového }
end. { program }                            { režimu                   }

XX.10. 

Bitově orientované podprogramy

Tento oddíl popisuje prostředky, implementované jednotkou Graph pro přístup k jednotlivým pixelům rastru zobrazovací plochy a zpracování obdélníkových výřezů zobrazovací plochy.

function GetPixel (X, Y: Integer): Word;

Vrací barvu pixelu o souřadnicích XY (hodnotu pixelu ve videopaměti). Pro pixely mimo zobrazovací plochu je vrácena hodnota 0 (barva pozadí).

procedure PutPixel (X, Y: Integer; Barva: Word);

Obarví pixel o souřadnicích XY barvou Barva (zapíše hodnotu Barva na pozici pixelu ve videopaměti). Pro pixely mimo zobrazovací plochu se neprovede nic.

procedure GetImage (X1, Y1, X2, Y2: Integer; var Mapa);

V proměnné Mapa vytvoří bitovou mapu obdélníkového výřezu obrazovky, definovaného relativními souřadnicemi jeho protilehlých rohů X1Y1X2Y2 (okraje výřezu jsou rovnoběžné s okraji obrazovky).

Souřadnice jsou vztaženy k počátku aktuálního výstupního okna, nesmí však být záporné. Vpravo a dolů výřez přesahovat hranici okna smí.

Parametrem Mapa může být proměnná libovolného typu, její velikost však musí být alespoň rovna velikosti vytvořené bitové mapy (funkce ImageSize). Maximální povolená plocha výřezu je tedy dána realizovatelnou velikostí jeho mapy, které je limitována maximální možnou velikostí proměnné — 64 KB. Hodnotou prvního resp. druhého slova mapy je o jedničku zmenšená šířka resp. výška výřezu (počet pixelů), třetí slovo je rezervováno a zbytek tvoří data, získaná z videopaměti adaptéru.

function ImageSize (X1, Y1, X2, Y2: Integer): Word;

Vrací velikost bitové mapy specifikovaného výřezu (počet bytů). Výřez je specifikován souřadnicemi X1Y1X2Y2 jeho protilehlých rohů. Pokud vypočtená velikost přesahuje limit 64 KB, funkce vrací nulu a generuje chybový kód (–11).

procedure PutImage (Xl, Yh: Integer; var Mapa; Rezim: Word);

Zapíše bitovou mapu Mapa do videopaměti adaptéru — zobrazí odpovídající výřez. Poloha výřezu na obrazovce je specifikována souřadnicemi XlYh jeho levého horního rohu (relativními vůči počátku aktuálního výstupního okna), rozměry výřezu jsou součástí mapy. Výřez není ořezáván hranicí okna (ani v případě, kdy je ořezávání nastaveno). Pokud však přesahuje levý, pravý nebo horní okraj obrazovky, není vůbec zobrazen.

Parametr Rezim definuje požadovaný způsob zápisu mapy do videopaměti. Pokud je jeho hodnotou 0 resp. 4, jsou barvy pixelů ve videopaměti přepisovány barvami pixelů z bitové mapy resp. jejich bitovými negacemi. Při ostatních hodnotách jsou v mapě předepsané barvy kombinovány s barvami původními — do videpaměti zapsaná barva pixelu je vypočtena jako hodnota bitové operace xor (1), or (2) resp. and (3).

const NormalPut = 0;
      CopyPut   = 0;
      XorPut    = 1;
      OrPut     = 2;
      AndPut    = 3;
      NotPut    = 4;

Tyto konstanty jsou jednotkou Graph deklarovány pro reprezentaci pěti režimů zápisu barev pixelů do videopaměti (konstanty NormalPutCopyPut jsou ekvivalentní). Všechny mohou být použity ve volání procedury PutImage (zápis bitové mapy) a první tři i ve volání procedury SetWriteMode (režim zápisu pixelů čar).


PŘÍKLAD: Následují ukázky jednoduchých operací s bitovými mapami. Uvedené procedury jsou funkční pouze pro výřezy dostatečně malé (velikost bitové mapy nesmí překročit 64 KB) a nejsou ošetřeny proti vstupně-výstupním chybám.

{----------------------------------------------------------------------}
procedure ImageCopy (X1, Y1, X2, Y2, X, Y: Integer; Zapis: Word);
{----------------------------------------------------------------------}
{ Kopíruje výřez, specifikovaný souřadnicemi X1, Y1 a X2, Y2 jeho      }
{ protilehlých rohů. Polohu kopie na obrazovce určují souřadnice X, Y  }
{ jejího levého horního rohu. Parametr Zapis je režim zápisu.          }

 var Mapa : Pointer;                  { ukazatel na bitovou mapu       }
     Vel  : Word;                     { velikost mapy                  }

begin { ImageCopy }
 Vel := ImageSize(X1, Y1, X2, Y2);    { výpočet velikosti mapy zdroje  }
 GetMem(Mapa, Vel);                   { založení dynamické proměnné    }
                                      { pro přenos mapy                }
 GetImage(X1, Y1, X2, Y2, Mapa^);     { vytvoření bitové mapy zdroje   }
 PutImage(X, Y, Mapa^, Zapis);        { zápis mapy na požadované místo }
                                      { požadovaným způsobem           }
 FreeMem(Mapa, Vel)                   { uvolnění dynamické proměnné    }
end; { ImageCopy }

{----------------------------------------------------------------------}
procedure ImageSave (X1, Y1, X2, Y2: Integer; Soubor: string);
{----------------------------------------------------------------------}
{ Založí diskový soubor a uloží do něj bitovou mapu výřezu. Parametry  }
{ X1, Y1 a X2, Y2 jsou souřadnice protilehlých rohů výřezu, Soubor je  }
{ systémová specifikace souboru.                                       }

 var Mapa : Pointer;                  { ukazatel na bitovou mapu       }
     Vel  : Word;                     { velikost mapy                  }
     F    : file;                     { cílový soubor mapy             }

begin { ImageSave }
 Vel := ImageSize(X1, Y1, X2, Y2);    { výpočet velikosti mapy zdroje  }
 GetMem(Mapa, Vel);                   { založení dynamické proměnné    }
                                      { pro přenos mapy                }
 GetImage(X1, Y1, X2, Y2, Mapa^);     { vytvoření bitové mapy zdroje   }
 Assign(F, Soubor);                   { inicializace souboru           }
 Rewrite(F, Vel);
 BlockWrite(F, Mapa^, 1);             { zápis mapy do souboru          }
 Close(F);                            { zavření souboru                }
 FreeMem(Mapa, Vel)                   { uvolnění dynamické proměnné    }
end; { ImageSave }

{----------------------------------------------------------------------}
procedure ImageLoad (X, Y: Integer; Soubor: string; Zapis: Word);
{----------------------------------------------------------------------}
{ Přečte a zobrazí bitovou mapu ze souboru Soubor. Parametry X, Y jsou }
{ souřadnice levého horního rohu obrazu mapy, Zapis je režim zápisu.   }

 var Mapa : Pointer;                  { ukazatel na bitovou mapu       }
     Vel  : Word;                     { velikost mapy                  }
     F    : file;                     { zdrojový soubor mapy           }

begin { ImageLoad }
 Assign(F, Soubor);                   { inicializace souboru           }
 Reset(F, 1);
 Vel := ImageSize(X1, Y1, X2, Y2);    { velikosti mapy = velikost soub.}
 GetMem(Mapa, Vel);                   { založení dynamické proměnné    }
                                      { pro přenos mapy                }
 BlockRead(F, Mapa^, Vel);            { načtení mapy ze souboru        }
 Close(F);                            { zavření souboru                }
 PutImage(X, Y, Mapa^, Zapis);        { zápis mapy na požadované místo }
                                      { požadovaným způsobem           }
 FreeMem(Mapa, Vel)                   { uvolnění dynamické proměnné    }
end; { ImageLoad }

XX.11. 

Stránky

Některé vidoadaptéry (z podporovaných EGA, VGA a Hercules) umožňují rozdělení videopaměti na části, které jsou zobrazovány jako samostatné textové či grafické stránky. Počet dostupných stránek pak závisí jednak na celkové kapacitě videopaměti adaptéru, jednak na paměťové náročnosti použitého textového či grafického módu zobrazení.

Tabulka 20: Podpora stránek v grafických módech adaptéru VGA
mód rozlišení barvy stránky
0 640 × 200 16 4
1 640 × 350 16 2
2 640 × 480 16 1

procedure SetActivePage (Stranka: Word);

Vybere stránku, na niž budou směrovány veškeré grafické výstupy. Parametr Stranka je pořadí vybrané stránky od začátku videopaměti (číslováno od nuly). Implicitně je aktivní stránka nultá.

procedure SetVisualPage (Stranka: Word);

Vybere stránku, která má být zobrazena na monitoru. Parametr Stranka je pořadí vybrané stránky od začátku videopaměti (číslováno od nuly). Implicitně je zobrazena stránka nultá.

XX.12. 

Začlenění grafických ovladačů a písem do kódu programu

Používané grafické ovladače a vektorová písma mohou být společně s programem distribuovány buď v samostatných souborech (zpravidla umístěných v pracovním adresáři programu či jeho podadresáři) nebo mohou být začleněny přímo do jeho kódu.

Mechanismus připojení libovolných externích dat do cílového exe-souboru programu využívá direktivy external, která jinak slouží k připojení assemblerských podprogramů, přeložených do vnitřního přemístitelného formátu Turbo Pascalu (tzv. „object-kód“). Ve zdrojovém textu programu (či jednotky) je deklarována pouze hlavička externího podprogramu, místo jeho těla je uvedena direktiva external. Tělo externího podprogramu je pak při kompilaci programu převzato ze souboru, jehož specifikaci obsahuje direktiva kompilátoru {$L soubor} (umístěná kdekoli ve zdrojovém textu).

Ke konverzi datových souborů z binárního do přemístitelného formátu se používá utilita binobj.exe (je k dispozici v podadresáři bin adresáře Turbo Pascalu) se syntaxí příkazové řádky

binobj.exe zdroj cíl identifikátor
Parametr zdroj resp. cíl je systémová specifikace původního (konverzi podrobovaného) resp. výsledného souboru, implicitní přípona je .bin resp. .obj. Parametr identifikátor je veřejné jméno, shodné s identifikátorem podprogramu, jehož tělem se takto označená data mají stát.

Aplikací popsaných kroků na zdrojový text programu a jím používané grafické ovladače a písma budou část kódu cílového exe-souboru tvořit „falešné“ podprogramy. Tyto podprogramy sice nesmí být spouštěny, jejich adresy však mohou být předány funkcím RegisterBGIDriverRegisterBGIFont, které zajistí jejich zaregistrování do grafického systému.

function RegisterBGIDriver (Driver: Pointer): Integer;

Zaregistruje přítomnost grafického ovladače na adrese Driver v operační paměti. Pokud na specifikované adrese není rozpoznán platný ovladač nebo je již inicializována grafika, vrací funkce záporné číslo grafické chyby (následně jej lze získat i voláním funkce GraphResult), v opačném případě (nezáporné) vnitřní identifikační číslo ovladače (není totožné s identifikačním číslem ovladače, používaným ve volání procedury InitGraph).

Zaregistrovaný ovladač lze pak inicializovat běžným způsobem — voláním procedury InitGraph s odpovídajícím číslem adaptéru a požadovaného grafického módu. Hodnota třetího parametru procedury (specifikace adresáře ovladače) je ignorována, takže může být libovolná (zpravidla se uvádí prázdný řetězec).

function RegisterBGIFont (Font: Pointer): Integer;

Zaregistruje přítomnost grafického písma na adrese Driver v operační paměti. Pokud na specifikované adrese není rozpoznáno platné písmo, vrací funkce záporné číslo grafické chyby (následně jej lze získat i voláním funkce GraphResult), v opačném případě (nezáporné) identifikační číslo ovladače, které lze dále požívat ve volání procedury SetTextStyle.


PŘÍKLAD: Do kódu exe-souboru následujícího programu bude začleněn ovladač egavga.bgi a písmo trip.chr.

{======================================================================}
program RegisterBgiDemo;
{======================================================================}

 uses Graph;
 var  Gd, Gm : Integer;                  { čísla graf. ovladače a módu }
      Font   : Integer;                  { číslo grafického písma      }

 procedure EGAVGADriver; external;       { grafický ovladač, připojený }
 {-------------------------------}       { ke kódu programu ze souboru }
 {$L c:\bp70\bgi\egavga.obj}             { c:\bp70\bgi\egavga.obj      }

 procedure TriplexFont; external;        { vektorové písmo, připojené  }
 {------------------------------}        { ke kódu programu ze souboru }
 {$L c:\bp70\bgi\trip.obj}               { c:\bp70\bgi\trip.obj        }

begin { program }
 if RegisterBGIDriver(@EGAVGADriver) < 0 then  { je ovladač v pořádku? }
  begin
   Writeln('Neplatný ovladač!');               { zpráva o neúspěchu    }
   Halt(1)
  end;
 Font := RegisterBGIFont(@TriplexFont);        { je font v pořádku?    }
 if Font < 0 then
  begin
   Writeln('Neplatné písmo!');                 { zpráva o neúspěchu    }
   Halt(2)
  end;
 Gd := 9; Gm := 2;                             { použit instalovaný    }
 InitGraph(Gd, Gm, '');                        { grafický ovladač      }
 SetTextStyle(Font, 0, 3);                     { a instalované písmo   }
 SetTextJustify(CenterText, CenterText);
 OutTextXY(320, 240, 'OVLADAČ I PÍSMO O.K.');  { zpráva o úspěchu      }
 Readln;                                       { čekání na stisk ENTER }
 CloseGraph                                    { úklid                 }
end. { program }

V okamžiku překladu uvedeného programu musí být již připraveny oba externí soubory s object-kódem ovladače a písma. Z příkazové řádky operačního systému to lze zajistit následující dvojicí příkazů:

binobj.exe egavga.bgi egavga.obj egavgadriver
binobj.exe trip.chr trip.obj triplexfont