Kreslení
X Window System byl vyvíjen tak, aby mohl používat širokou škálu grafických karet a monitorů, od jednoduchých s několika málo stupni šedi až po truecolor s 24 i více bity barevné informace na pixel. Používá bitmapovou grafiku a barevná hodnota pixelu se vždy na výslednou barvu přepočítává prostřednictvím barevné palety. Typ palety a způsob přepočtu definuje visual. Jako základní barevný model se používá RGB, který je však device-dependent, tj. stejně zadaná barva může na různých monitorech vypadat jinak. Od verze X11R5 je možné používat device-independent specifikace barev Xcms (X Color Management System). Určitá barva zadaná v některém z Xcms barevných prostorů by měla vypadat stejně na každém správně zkalibrovaném monitoru. Kromě zadání barvy pomocí hodnot jejích složek v některém barevném prostoru je možné používat jména barev. X má tabulku pro převod mezi jmény a hodnotami barev.
X rozlišuje virtuální palety definované pro jednotlivá okna a fyzickou paletu, kterou používá grafický adaptér pro zobrazování. Window manager instaluje virtuální palety do fyzické pomocí XInstallColormap. Jestliže nelze současně instalovat všechny virtuální palety, window manager se snaží instalovat alespoň palety patřící aktuální aplikaci – typicky té, v jejímž okně je kurzor myši – a tím zajistit její správné zobrazení. Okna ostatních aplikací pak mohou být zobrazena v nesprávných barvách. Klient si alokuje položky palety voláním funkcí XAllocColor, XAllocNamedColor, XcmsAllocColor neboXcmsAllocNamedColor. Vždy je potřeba zadat barvu a funkce vrátí index do palety, tj. hodnotu pixelu, kterou je potřeba použít při kreslení, aby se zobrazila požadovaná barva. Takto alokované položky palet jsou read-only, tzn. jejich barvu nelze dodatečně měnit. Jejich výhoda je, že mohou být sdíleny několika klienty. Pokud je paleta měnitelná, dají se v ní alokovat kromě read-only i read/write položky. Taková položka nemůže být sdílená. Klient, který ji alokoval, může kdykoliv změnit její obsah, a tím změnit barvu všech pixelů, jež byly nakresleny s hodnotou odpovídající indexu této položky.
Typy palet použitelné na určité obrazovce závisí na tom, jaké visuals podporuje X server. Pro obrazovky schopné zobrazovat pouze stupně šedi existují třídy visuals GrayScale (měnitelná paleta) a StaticGray (neměnná paleta). Paleta je jednosložková, hodnota pixelu se interpretuje jako index do palety a v položce palety se najde odpovídající hodnota jasu. Barevné obrazovky s malou bitovou hloubkou – nejčastěji 8 bitů – používají třídy visuals PseudoColor
(měnitelná paleta) a StaticColor (neměnná paleta). Paleta je opět jednosložková, ale položka palety se interpretuje jako tři hodnoty pro barevné složky R, G a B. Při použití velké bitové hloubky – např. 24 bitů – by jednosložková paleta byla příliš velká (224 položek). Proto existují třídy visual DirectColor (neměnná paleta) a TrueColor (měnitelná paleta). Ty mají třísložkové palety. Hodnota pixelu se rozdělí na tři čísla. Každé se použije jako index do jedné části palety pro jednu barevnou složku. Výsledné hodnoty dají dohromady barvu. Při osmi bitech na každou složku je takto potřeba pouze 3.28
položek palety. Na dnešních grafických kartách se typicky používá visual TrueColor s barevnou hloubkou 24 bitů, kdy hodnoty pixelů jsou stejné jako obsah příslušných položek palety, takže paleta pozbývá na významu.Množina grafických primitiv v X je relativně malá, ale doplňují ji různá rozšíření, např. Render pro 2D grafiku včetně antialiasovaného textu a OpenGL pro 3D grafiku. My se zde zaměříme pouze na základní grafické možnosti X bez rozšíření. Kreslit se v X dá do tzv. drawables, což jsou okna a pixmapy. Pixmapa je bitmapový obrázek uložený na serveru. Obsah pixmapy se dá zkopírovat do okna pomocí XCopyArea nebo XCopyPlane.
Parametry kreslení se drží na serveru v grafickém kontextu. V požadavku na nakreslení grafického elementu se pak zadávají pouze souřadnice bodů a ID grafického kontextu, ale nemusí se přenášet hodnoty všech parametrů. Grafický kontext se vytváří funkcí XCreateGC a ruší funkcíXFreeGC. Jeho obsah lze měnit pomocí XChangeGC nebo XCopyGC, popř. je možné individuálně nastavovat jednotlivé parametry: XSetLineAttributes, XSetFileRule, XSetFunction, atd. Hodnoty v grafickém kontextu se dají i číst voláním XGetGCValues. Záleží na konkrétní situaci, zda je lepší mít jeden grafický kontext a měnit jeho parametry, nebo si předem připravit několik různě nastavených grafických kontextů.
Funkce XSetLineAttributes a XSetDashes nastavují parametry čar. Základní parametr je tloušťka čáry. Speciální hodnota 0 znamená čáru o šířce 1 pixel kreslenou rychlejším algoritmem než ostatní čáry. Čáry s tloušťkou 0 se mohou na různých serverech lišit, čáry s tloušťkou větší vypadají všude stejně. Dále se zadává styl čáry: LineSolid (plná čára), LineOnOffDash (přerušovaná čára) a LineDoubleDash(čára kreslená střídavě barvou popředí a pozadí). Druhý a třetí styl používají definici délek úseků přerušované čáry v parametrech dashes a dash_offset. Možnosti zakončení čáry jsou na obr. 1. Varianta CapNotLast funguje jen pro čáry šířky 0 a 1. Pokud se jedním požadavkem nakreslí několik spojených čar, dá se nastavit způsob propojení v místech napojení jednotlivých čar, viz obr. 2.
Obr. 1: Zakončení čar
Obr. 2: Spojení čar
Pro kreslení textu je nutné v grafickém kontextu nastavit font pomocí XSetFont. Před použitím je nutné nahrát font funkcí XLoadFont. Když potřebujeme znát metriky jednotlivých znaků, můžeme volat XLoadQueryFont. Každý font je v paměti pouze jednou, server ho uvolní z paměti, když ho všichni klienti přestanou používat, tj. když skončí nebo zavolají XFreeFont či XUnloadFont.
Pro kreslení vyplněných polygonů je nutné specifikovat pravidlo pro vyplňování (fill_rule). Varianty jsou EvenOddRule (bod je vyplněn, jestliže nekonečně dlouhý paprsek vycházející z tohoto bodu protíná obrys v lichém počtu průsečíků), nebo WindingRule (paprsek protíná různý počet levotočivých a pravotočivých segmentů obrysu). Rozdíl mezi těmito dvěma pravidly je vidět na obr. 3. Dva způsoby vyplňování oblouků (arc_mode) jsou ukázány na obr. 4.
Obr. 3: Vyplňování polygonů
Obr. 4: Vyplňování oblouků
Standardně se při kreslení provádí ořezávání podle obrysu okna, tj. nelze kreslit mimo okno. Pomocí parametru subwindow_mode se dá zapnout ořezávání i podle synovských oken (ClipByChildren, standardní nastavení, kdy synovské okno leží na rodiči a zakrývá ho) nebo kreslení přes obsah synovských oken (IncludeInferiors). Oblast ovlivněnou kreslením lze dále redukovat nastavením ořezávací masky (clip_mask, funkceXSetClipMask, XASetClipRectangles a XSetRegion). To je bitmapa určující, které pixely se budou překreslovat a které zůstanou nezměněny. Příklad ořezávací masky je na obr 5, kde se z šedého obdélníku nakreslí jen tmavě šedá část.
Obr. 5: Ořezávání
Kreslení vyplněných oblastí se řídí parametrem fill_style. Nejjednodušší je vyplňování barvou popředí (FillSolid) nastavenou v parametru foreground. Druhá možnost je použít pro vyplňování pixmapu (FillTiled). Třetí varianta (FillStippled) je použití bitmapy (pixmapy s jedním bitem na pixel). Kreslit barvou popředí se budou pouze ty pixely, jež mají v bitmapě hodnotu 1. Poslední způsob vyplňování je FillOpaqueStipled, kdy se barvou popředí kreslí pixely s hodnotou 1 v bitmapě a barvou pozadí pixely s hodnotou 0. Ve speciálních případech je možné změnou plane_mask nastavit, že kreslení bude pracovat jen s některými bitovými rovinami okna. Normálně se stará hodnota pixelu zapomene a nahradí se nově kreslenou hodnotou. Je ale možné tyto dvě hodnoty zkombinovat po jednotlivých bitech. K dispozici je všech 16 existujících binárních funkcí dvou binárních proměnných.
Xlib poskytuje funkce na kreslení jednotlivých bodů (XDrawPoint), úseček (XDrawLine), lomených čar (XDrawLines, XDrawSegments a XFillPolygons), obdélníků (XDrawRectangle, XDrawRectangles, XFillRectangle aXFillRectangles) a oblouků (XDrawArc, XDrawArcs, XFillArc a XFillArcs). Funkce začínající na XDraw kreslí jen obrysy. Funkce začínající na XFill kreslí vyplněné objekty. Počet objektů, jež lze nakreslit jedním voláním, závisí na maximální velikosti požadavku X protokolu. Toto maximum – udávané v jednotkách o velikosti čtyři bajty) se dá zjistit voláním XMaxRequestSize. Maximum minus 3 udává maximální počet bodů. Počet úseček a obdélníků je poloviční, počet oblouků je třetinový. Veškeré rozměry se udávají v pixelech. Je nutné si dávat pozor na to, že stejně zadané rozměry znamenají při kreslení obrysů a vyplněných objektů něco jiného, jak je znázorněno na obr. 6.
Obr. 6: Obrys a vyplnění
X Window System podporuje 8bitové a 16bitové fonty. Kreslení řetězců pomocí fontu nastaveného v grafickém kontextu provádí funkce XDrawString a XDrawString16. Tyto funkce kreslí pouze jednotlivé znaky barvou popředí. Alternativně lze použít XDrawImageString a XDrawImageString16, které navíc kolem textu nakreslí obdélník (bounding box) barvou pozadí. Několik řetězců na jednom řádku se dá nakreslit jedním voláním XDrawText nebo
XDrawText16. Pro každý řetězec se specifikuje font a horizontální posun vůči konci předchozího řetězce. Pozice textu při kreslení se zadává pomocí souřadnic začátku účaří (baseline).
V rámci podpory jiných jazyků než angličtiny se v X11R5 kromě jednoho fontu dá použít i sada fontů (XFontSet), což je množina fontů obsahujících dohromady všechny znaky potřebné pro zobrazení textu v určitém locale (národním prostředí). Pro zobrazení textu přibyly funkce s prefixem Xwc, jež používají řetězce typu wchar_t , tj. s vícebajtovými znaky s pevným počtem bajtů na každý znak. Dále přibyly funkce s prefixem Xmb. Ty používají řetězce typu char , kde mohou být různé znaky kódovány různým počtem bajtů. V XFree86 existují navíc funkce s prefixem Xutf8 pro práci s Unicode řetězci v kódování UTF-8. X11R6 přineslo další zobecnění zavedením výstupních metod.
Seznam dostupných fontů lze zjistit pomocí XListFonts a XListFontsWithInfo. Jména fontů se zadávají ve formě XLFD (X Logical Font Description). Každý font má jméno skládající se z částí oddělených pomlčkami, např. -misc-fixed-bold-r-normal–13–120–75–75-c-70-iso8859–2. Jednotlivé části jména definují vlastnosti fontu, např. rodinu fontů (fixed), velikost v pixelech (13), velikost v bodech (120) a kódování (iso8859–2). Dají se používat wildcardy, např.
---medium-i-–10---75----2. X server vybere první odpovídající font. Pokud v seznamu získaném funkcí XListFonts nebo utilitou xlsfonts narazíme na jméno fontu, které obsahuje nulovou velikost, jedná se o škálovatelný font. Ve volání XLoadFont můžeme nulu nahradit libovolným číslem, a tím nastavit potřebnou velikost fontu. Aby bylo možné vypisované texty správně umístit na obrazovku, je nutné znát rozměry jednotlivých znaků – metriky fontu a všech jeho znaků. Tyto informace je možné získat pomocí funkcí XQueryFont a XLoadQueryFont ve formě struktur XFontStruct (metriky fontu) a XCharStruct
(metriky znaků). Význam metrických informací je vidět na obr. 7.
Obr. 7: Metriky fontů