Obsah
1. Pětice zásobníků a způsob jejich využití
2. Zásobník operandů
3. Zásobník slovníků
4. Zásobník spustitelných objektů
5. Zásobník grafických stavů
6. Zásobník ořezových cest
7. Odkazy na další informační zdroje
8. Obsah dalšího pokračování tohoto seriálu
1. Pětice zásobníků a způsob jejich využití
Interpreter PostScriptu pracuje celkem s pěti typy zásobníků. Jedná se o zásobník operandů (operand stack), zásobník slovníků (dictionary stack), zásobník spustitelných objektů (execution stack), zásobník grafických stavů (graphics state stack) a konečně zásobník ořezových cest (clipping path stack). V předchozích částech tohoto seriálu, ve kterých jsme si ukazovali krátké programy vytvořené v PostScriptu, jsme převážně pracovali se zásobníkem operandů (právě zde se uplatnil zápis aritmetických a logických operací pomocí převrácené polské notace – RPN) a interpreter nepřímo pracoval také se zásobníkem slovníků a zásobníkem spustitelných objektů. V dalším textu si popíšeme, k jakým operacím je možné jednotlivé zásobníky použít.
2. Zásobník operandů
Zásobník operandů (operand stack) již velmi dobře známe. Tento zásobník je použit především při vyhodnocování aritmetických a logických výrazů pomocí RPN (Reverse Polish Notation). Kromě toho se přes zásobník operandů předávají parametry systémovým i uživatelským funkcím (například se jedná o příkaz moveto, který ze zásobníku vyčte dvě číselné hodnoty představující souřadnice bodu) a tyto funkce mohou na zásobník operandů vracet nějaké výsledky. I operátory/příkazy pro tvorbu programových smyček tento zásobník využívají – jak pro specifikaci počtu průběhů smyčky a mezních hodnot počitadla, tak i pro průběžné ukládání aktuální hodnoty počitadla. Pro manipulaci s hodnotami uloženými na tomto zásobníku slouží operátory dup, pop, exch, copy, roll, count, clear, index, mark, counttomark a cleartomark, jejichž bližší popis je uveden v následující tabulce:
Operátor | Význam operátoru |
---|---|
clear | vymazání všech objektů ze zásobníku (vyprázdnění zásobníku operandů) |
count | na zásobník operandů se uloží celé číslo reprezentující počet položek v něm uložených (aktuální hloubka zásobníku) |
copy | na zásobníku operandů se zduplikuje posledních n položek (n je uloženo na vrcholu zásobníku) |
dup | duplikace (kopie) hodnoty uložené na vrcholu zásobníku operandů |
pop | opak předchozího operátoru – odstranění položky z vrcholu zásobníku (ve Forthu se jednalo o příkaz „drop“ se stejným významem) |
exch | prohození dvou položek uložených na nejvyšších dvou místech zásobníku operandů, bez ohledu na datový typ položek |
index | na vrchol zásobníku operandů se zkopíruje n-tá položka |
mark | na zásobník se uloží značka (speciální hodnota použitá v následujích dvou operátorech) |
cleartomark | vymazání nejvyšších položek na zásobníku až po vloženou značku |
counttomark | na zásobník se uloží počet všech nalezených položek až po vloženou značku |
Mezi aritmetické operátory a funkce, které využívají zásobník operandů pro získání hodnot operandů a vrací na zásobník výsledek dané operace, patří:
Operátor | Význam operátoru |
---|---|
add | součet dvou hodnot uložených na nejvyšších dvou místech zásobníku operandů |
sub | rozdíl dvou hodnot uložených na nejvyšších dvou místech zásobníku operandů |
mul | součin dvou hodnot uložených na nejvyšších dvou místech zásobníku operandů |
div | podíl dvou hodnot uložených na nejvyšších dvou místech zásobníku operandů |
idiv | podíl dvou celočíselných hodnot |
mod | výpočet zbytku po dělení dvou celočíselných hodnot |
abs | na zásobník se vrátí absolutní hodnota přečtená z jeho nejvyššího místa (TOS) |
neg | otočení znaménka hodnoty uložené na nejvyšším místě zásobníku operandů |
ceiling | zaokrouhlení hodnoty uložené na nejvyšším místě zásobníku operandů směrem nahoru |
floor | zaokrouhlení hodnoty uložené na nejvyšším místě zásobníku operandů směrem dolů |
round | zaokrouhlení hodnoty uložené na nejvyšším místě zásobníku operandů k nebližší celočíselné hodnotě |
truncate | odříznutí desetinné části hodnoty uložené na nejvyšším místě zásobníku operandů |
sqrt | výpočet druhé odmocniny hodnoty uložené na nejvyšším místě zásobníku operandů |
atan | výpočet arkustangenty z podílu dvou hodnot chápaných jako údaj ve stupních (odpovídá funkci atan2() v céčku) |
sin | sinus hodnoty uložené na TOS (zadaný úhel je ve stupních, ne v radiánech) |
cos | kosinus hodnoty uložené na TOS (zadaný úhel je ve stupních, ne v radiánech) |
ln | přirozený logaritmus hodnoty uložené na TOS |
log | desítkový logaritmus hodnoty uložené na TOS |
epx | výpočet xy, obě požadované hodnoty jsou uložené na zásobníku operandů |
rand | vygenerování pseudonáhodného celého čísla (typu int) a uložení na TOS |
srand | inicializace generátoru pseudonáhodných čísel (RND) z hodnoty uložené na TOS |
rrand | vrácení inicializační hodnoty generátoru pseudonáhodných čísel (RND) na TOS |
Zkratkou TOS je v předchozích dvou tabulkách myšlena nejvyšší obsazená pozice na zásobníku operandů; samotná zkratka má význam Top Of Stack a používá se mj. i v literatuře o programovacím jazyku Forth.
3. Zásobník slovníků
Zásobník slovníků (dictionary stack) může obsahovat – jak již ostatně jeho jméno napovídá – pouze objekty, které jsou typu slovník (v dalším textu se dozvíme, že slovníky nejsou nic jiného než asociativní pole či hashmapy známé z dalších programovacích jazyků). Interpreter PostScriptu z tohoto zásobníku čte hodnoty ve všech případech, kdy při procházení programu nalezne nějaké slovo či symbol. Může se jednat o systémový příkaz, uživatelskou funkci, jméno fontu, který byl načten příkazem findfont atd. Systémové příkazy jsou uloženy ve slovníku nazvaném system dictionary, uživatelské příkazy ve slovníku user dictionary, jména fontů ve slovníku fontů atd. Pro získání těchto slovníků je možné použít následující příkazy/operátory:
Operátor | Význam operátoru |
---|---|
systemdict | na TOS zásobníku operandů se uloží odkaz na systémový slovník |
globaldict | na TOS zásobníku operandů se uloží odkaz na globální slovník (globální virtuální paměť – VM) |
userdict | na TOS zásobníku operandů se uloží odkaz na uživatelský slovník (lokální virtuální paměť) |
currentdict | na TOS zásobníku operandů se uloží právě aktivní slovník (ten, který je na TOS zásobníku slovníků). Na tento zásobník se slovníky ukládají pomocí operátoru begin |
Pro manipulaci s celými slovníky nebo „pouze“ s jejich obsahem je možné použít mnoho operátorů, které jsou vypsány v následující tabulce:
Operátor | Význam operátoru |
---|---|
length | vrací počet položek uložených ve slovníku, jehož odkaz je na TOS zásobníku operandů |
maxlength | vrací maximální počet položek, které je možné uložit do slovníku, jehož odkaz je na TOS zásobníku operandů |
countdictstack | vrací počet položek uložených na zásobníku slovníků |
cleardictstack | odstraní všechny odstranitelné slovníky ze zásobníku slovníků |
dict | vytvoření nového slovníku, jméno slovníku a jeho kapacita je uložena na TOS zásobníku operandů |
<< | začátek vytváření slovníku |
>> | konec vytváření slovníku |
begin | na vrchol zásobníku slovníku se uloží odkaz na slovník získaný z TOS zásobníku operandů |
end | z vrcholu zásobníku slovníků se odstraní zde uložený odkaz na slovník |
def | uložení dvojice klíč-hodnota do aktivního slovníku (klíč a hodnota jsou uloženy na nejvyšších dvou místech zásobníku operandů) |
store | přepis dvojice klíč-hodnota novou dvojicí (nevznikají duplicity) |
load | prohledání zásobníku slovníků a vrácení hodnoty odpovídající klíči (ten je uložen na TOS zásobníku operandů) |
get | podobné operátoru load, ale prohledává se slovník uložený na zásobníku operandů |
put | na slovník uložený v zásobníku operandů se uloží dvojice klíč-hodnota |
undef | odstranění dvojice klíč-hodnota ze slovníku, jehož odkaz je uložen na zásobníku operandů |
known | test, zda slovník obsahuje daný klíč |
forall | pro každý prvek ve slovníku se zavolá určená procedura |
Při práci se slovníky se nejčastěji používají operace get, put, undef a known. Všechny operace předpokládají, že je identifikátor (či odkaz) na požadovaný slovník uložený na zásobníku operátorů. Kromě toho se na tento zásobník ukládají i další potřebné parametry, tj. klíče a k nim přiřazené hodnoty.
Operátor get očekává parametry (slovník, klíč), operátor put parametry (slovník, klíč, hodnota) a operátor known i undef parametry (slovník, klíč). Výsledek operace je uložen na TOS zásobníku operandů. Buď se jedná o nalezenou hodnotu (get), nebo o hodnotu true/false (known). Do světa funkcionálních jazyků nás zavádí operátor forall, pomocí něhož je možné na všechny prvky uložené ve slovníku zavolat zadanou proceduru bez nutnosti explicitního zápisu smyčky. Očekávané parametry tohoto operátoru jsou (slovník, procedura).
4. Zásobník spustitelných objektů
Zásobník spustitelných objektů (execution stack) je používán interpreterem PostScriptu pro úschovu objektů, které jsou v dané chvíli spuštěny. V tomto zásobníku bývají typicky uložené volané, tj. spuštěné procedury a identifikátory otevřených souborů. Jakmile je zavolána nějaká procedura, je reference na ni (plus bod návratu) uložen na zásobník spustitelných objektů a při ukončení procedury se její reference z tohoto zásobníku odstraní, čímž se na vrchol zásobníku (TOS – Top Of Stack) vrátí původní (volající) procedura.
V určitém ohledu, zejména způsobem použití, se tento zásobník podobá zásobníku návratových adres (Return Stack) použitý ve Forthu. Narozdíl od Forthu však není možné obsah tohoto zásobníku přímo modifikovat programovým kódem (ve Forthu bylo možné přenášet údaje ze zásobníku návratových adres do zásobníku operandů a naopak).
5. Zásobník grafických stavů
Na zásobník grafických stavů (graphics state stack) je možné uložit aktuální grafický stav a po provedení nějaké operace (třeba kreslení jiným stylem čáry) se tento stav může ze zásobníku obnovit. Tento zásobník se v praxi používá poměrně často, zejména proto, že součástí grafického stavu je i CTM, tj. current transformation matrix – transformační matice používaná pro převod uživatelských souřadnic na souřadnice zařízení.
Grafický stav je možné na zásobník grafických stavů uložit příkazem gsave a obnovit pomocí příkazu grestore. V novějších verzích PostScriptu je možné z grafického stavu vytvořit objekt a pracovat s ním nezávisle na zásobníku grafických stavů. Pro tento účel slouží operátory gstate (vytvoření grafického objektu), currentgstate (kopie grafického stavu do vytvořeného objektu) a setgstate (zpětná kopie dat z objektu, ve kterém byl grafický stav uložený). V grafickém stavu jsou mj. uloženy tyto informace:
Název | Význam |
---|---|
CTM | aktuálně používaná transformační matice |
position | souřadnice aktuálního bodu (konce cesty), nastaveno například pomocí operátoru moveto |
path | interní identifikátor právě vytvářené cesty |
clipping path | interní identifikátor právě používané ořezové cesty |
color space | barvový prostor zařízení |
color | aktuálně nastavená barva vykreslování cesty nebo jejího vnitřku |
font | slovník tvarů jednotlivých znaků právě používaného fontu |
line width | šířka čáry konstruované cesty |
line cap | způsob ukončení širokých čar v cestě |
line join | způsob napojení širokých čar v cestě |
dash pattern | styl vykreslovaných čar |
color rendering | způsob převodu barev z barvového prostoru CIE-xy do interního barvového prostoru zařízení |
overprint | způsob vykreslování separovaných barev |
black generation | procedura, která je použita pro výpočet černé barvy při převodu z RGB do CMYK |
undercolor removal | procedura použitá ke kompenzaci barev při převodu z RGB do CMYK |
halftone | procedura či slovník použitý při halftoningu (nahrazování barevných přechodů vzorkem) |
flatness | tolerance zadaná v pixelech, která je použita při vykreslování Bézierových křivek |
6. Zásobník ořezových cest
Zásobník ořezových cest (clipping path stack) je použit k úschově a následnému výběru tvarů takzvaných ořezových cest (clipping path). Ořezová cesta je do tohoto zásobníku vložena příkazem clipsave a obnovena příkazem cliprestore. Kromě těchto dvou příkazů je možné zkombinovat ořezovou cestu s cestou právě konstruovanou (příkaz clip), popř. nahradit vytvářenou cestu kopií ořezové cesty (příkaz clippath).
Implicitní ořezová cesta zkonstruovaná interpreterem před započetím vytváření tiskové strany má tvar obdélníka, jehož hrany odpovídají okrajům tiskové strany. Jinými slovy to znamená, že je každá cesta či jiný vykreslovaný tvar ořezán přesně na okraji tiskové strany. Ořezové cesty je možné použít i při zobrazování bitmap, tj. rastrových obrázků. Použití této techniky, která má v praxi velké možnosti uplatnění, si ukážeme v následující části tohoto seriálu.
7. Odkazy na další informační zdroje
Práce se zásobníky je v PostScriptu podobná jako v dalších programovacích jazycích založených na převrácené polské notaci (RPN). Proto v odkazech na literaturu uvádím i materiály, které se týkají snad nejznámějšího zásobníkového jazyka – Forthu.
- Adobe Systems: PostScript Language Reference Manual, The Red Book,
Adobe Systems Incorporated, 2nd ed., Addison Wesley 1990. - Adobe Type 1 Font Format (včetně ukázek s použitím smyček),
Addison-Wesley - PostScript Language Program Design,
Addison-Wesley 1990, ISBN 0–201–14396–8 - PostScript Language Reference Manual,
Addison-Wesley 1990, ISBN 0–201–18127–4 - PostScript Language Tutorial and Cookbook,
Addison-Wesley 1990, ISBN 0–201–10179–3 - Pavel Herout:
PostScriptové fonty pro ty, co o nich moc nevědí - Pavel Tišnovský:
Programovací jazyk Forth,
/clanky/programovaci-jazyk-forth-a-zasobnikove-procesory - http://zforth.com/ – takzvaný The Forth Programming Webring, počátek řetězce stránek věnovaných Forthu a příbuzným tématům. Zajímavé je, že tento server je vytvořen pomocí systému zHTTP, který je napsaný v dialektu programovacího jazyka Forth nazvaného zForth.
- http://www.forth.com/ – úvodní stránka firmy Forth Inc., která vytváří komerční verze programovacího jazyka Forth spolu s propracovaným vývojovým prostředím, na stránce lze nalézt i odkaz na známý SwiftForth. Spoluzakladatelem této firmy je Chuck Moore.
- http://en.wikipedia.org/wiki/Forth_programming_language – stránka Wikipedie o programovacím jazyku Forth.
- http://en.wikipedia.org/wiki/Chuck_Moore – stránka Wikipedie o Chucku Moorovi, vynálezci Forthu.
- http://home.earthlink.net/~mrob/pub/lang_srom.html – porovnání programovacích jazyků podle názoru programátorů.
- http://www.jwdt.com/~paysan/gforth.html – GForth (GNU Forth)
- http://www.forth.com/resources/evolution/index.html – The Evolution of Forth – velmi dobře zpracovaná historie Forthu.
8. Obsah dalšího pokračování tohoto seriálu
V následující části tohoto seriálu dokončíme povídání o PostScriptu. Řekneme si, jakým způsobem je možné v PostScriptu (což je původně vektorový formát) používat bitmapy, tj. jak lze kombinovat vektorovou grafiku s grafikou rastrovou. Uvidíme, že v PostScriptu je možné bitmapy ukládat jak bezeztrátově, tak i pomocí ztrátové komprimace založené například na již dříve popsaném algoritmu JPEG.