Hlavní navigace

Historie vývoje GUI (9): použití PostScriptu v systému NeXTSTEP

14. 12. 2010
Doba čtení: 27 minut

Sdílet

V předchozím článku jsme se seznámili s počítači společnosti NeXT. Na těchto počítačích byl provozován systém NeXTSTEP, jehož nedílnou součástí byl i jazyk PostScript, resp. jeho varianta Display PostScript. Ten však byl využit i konkurenčním systémem NeWS firmy Sun. Řekneme si, proč byl používán pro GUI.

Obsah

1. Historie vývoje GUI (9): použití PostScriptu v systému NeXTSTEP

2. NeXTSTEP – první objektově orientovaný systém s GUI?

3. Základní informace o programovacím jazyku PostScript

4. Kreslení v PostScriptu s využitím cest

5. Bézierovy křivky a fonty v PostScriptu

6. Zásobníkový programovací jazyk a tvorba nových slov (funkcí)

7. Řídicí příkazy (podmínky a programové smyčky)

8. Display PostScript – použití PostScriptu při práci s obrazovkou (nejenom) v systému NeXTSTEP

9. Odkazy na další informační zdroje

1. Historie vývoje GUI (9): použití PostScriptu v systému NeXTSTEP

V předchozí části seriálu o historii vývoje grafických uživatelských rozhraní jsme si řekli, jakým způsobem vznikla společnost NeXT odchodem Steva Jobse a některých dalších klíčových zaměstnanců z firmy Apple v roce 1985. Taktéž jsme si popsali nejdůležitější technické parametry pracovních stanic vyráběných společností NeXT. Jednalo se jak o původní pracovní stanici první generace nazvanou NeXT Computer, tak i o druhou generaci těchto počítačů, především o hi-endový počítač NeXT Cube a poněkud levnější, ale cenově dostupnější NeXTstation a NeXTstation Color. Všechny počítače vyráběné firmou NeXT vynikaly jak svým nadstandardním výkonem (poměrně rychlý mikroprocesor spojený s DSP poskytoval výpočetní výkon až 15 MIPS a 2 MFLOPS), tak i na svou dobu vynikajícím grafickým rozlišením 1120×832 pixelů, rozhraním SCSI a standardně dodávanou síťovou kartou standardu Ethernet – to vše v době, kdy počítačové sítě budované pro platformu PC byly spíše výjimečnou záležitostí.

Obrázek 1: Pracovní stanice NeXTcube (tj. jedná se o druhou generaci počítačů firmy NeXT) i s monitorem, klávesnicí, myší a magnetooptickým diskem.

Ovšem nedílnou součástí počítačů NeXT, která je z historického hlediska dokonce mnohem důležitější než technické parametry hardwaru, byl i operační systém NeXTSTEP, jenž v sobě spojoval jak výkonnost a robustnost UNIXu, tak i mnoho nových konceptů, které v poněkud změněné podobě dodnes přežívají například v operačním systému Mac OS X. Základem operačního systému NeXTSTEP je upravené jádro, jež bylo původně převzaté ze systému Mach. Toto jádro bylo doplněné o některé tradiční unixové nástroje. Nad touto základní vrstvou byl postaven systém pro správu pracovní plochy a grafických oken, jejichž obsah se vykresloval s využitím Display PostScriptu, tj. systému založeného na programovacím jazyku PostScript, který byl upravený takovým způsobem, aby umožňoval práci s grafickou obrazovkou, souběžný běh více programů (s možností jejich vzájemné synchronizace), byl vybaven funkcemi pro zjištění pozice kurzoru myši vůči grafickým objektům (hit detection) atd.

Obrázek 2: Pracovní stanice NeXTstation Color se spuštěným operačním systémem.

Právě tímto programovacím jazykem se budeme podrobněji zabývat v následujících kapitolách. Ovšem i další součásti systému NeXTSTEP jsou zajímavé a v mnoha ohledech přelomové. Konkurenční operační systémy s grafickým uživatelským rozhraním byly v polovině osmdesátých let minulého století většinou naprogramovány v kombinaci assembleru (tj. nízkoúrov­ňového jazyka symbolických adres) a programovacího jazyka C, což dosti podstatným způsobem ovlivnilo jejich aplikační programové rozhraní (API) – ostatně nemusíme chodit pouze do dnes již poměrně vzdálené minulosti, protože například WinAPI systému Microsoft Windows nebo Xlib systému X mají stále API vycházející z céčka. Naproti tomu se tvůrci operačního systému NeXTSTEPu rozhodli použít pro nízkoúrovňové moduly taktéž programovací jazyk C (což není překvapivé, protože na céčko se i díky zvyšující se kvalitě překladačů programátoři dívali jako na „přenositelný assembler“), ovšem větší část systému byla napsána v programovacím jazyce Objective-C.

Obrázek 3: Grafické uživatelské rozhraní systému NeXTSTEP zobrazené na počítači NeXTstation s rozlišením 1120×832 pixelů ve čtyřech stupních šedi.

2. NeXTSTEP – první objektově orientovaný systém s GUI?

Programovací jazyk Objective-C je, podobně jako na osobních počítačích řady PC poněkud více známý a mnohem rozšířenější programovací jazyk C++, sice založen na původním céčku, ovšem přidává do něj objektové rysy. Oproti staticky typovanému C++ se však Objective-C přibližuje spíše ke klasicky pojatému „smalltalkovskému“ objektovému systému s posíláním zpráv a reflexí, díky níž se například objekt, jemuž je zpráva poslána, dokáže až v čase běhu programu rozhodnout, jakým způsobem a zda vůbec tuto zprávu zpracuje atd. Právě díky použití programovacího jazyka Objective-C bylo možné nad základními moduly operačního systému NeXTSTEP (jádro Mach, UNIXové utility, okenní systém, Display PostScript) vytvořit plně objektově orientovanou aplikační vrstvu, což bylo velmi důležité, protože to umožnilo vývojářům psát aplikace s grafickým uživatelským rozhraním poměrně snadno a rychle, zejména při porovnání s v té době existujícími nebo právě vyvíjenými konkurenčními systémy (Windows 3.x, GEOS, TOS+GEM, Amiga OS Workbench, X (+Motif)).

Obrázek 4: Historický správce oken (potomek původního NeXTSTEPu) s historickým webovým prohlížečem (Netscape Navigator Gold) běžící na dnes již historické grafické pracovní stanici.

Později byly k objektové aplikační vrstvě dodány různé doplňkové a rozšiřující kity, například PDO (Portable Distributed Objects) umožňující komunikaci mezi objekty „žijícími“ na různých počítačích, objektově-relační databáze atd. Spolu s vývojovým prostředím se Objective-C a objektová vrstva systému NeXTSTEP staly na několik let prakticky nejlepší platformou pro rychlý vývoj aplikací s GUI. To ostatně potvrdil například i Tim Berners-Lee, který řekl, že kdyby programování prvního webového prohlížeče probíhalo na jiném systému, než NeXTSTEP, byl by celý vývoj mnohem pracnější a možná by výsledek vypadal jinak (například některé rysy značkovacího jazyka HTML vychází z formátovacích možností widgetu pro práci s textem systému NeXTSTEP). Mezi další známé vývojáře, kteří systém NeXTSTEP používali, patří John Carmack, který právě zde vytvořil první demoverze her Wolfenstein 3D a Doom, jež byly posléze portovány na PC, které samozřejmě představovalo z komerčního hlediska mnohem zajímavější platformu.

Obrázek 5: První webový server na světě byl vyvinut i otestován na pracovní stanici NeXT Computer. Autorem tohoto projektu – a současně i webového prohlížeče WorldWideWeb a současně i samotného principu práce webu – byl Tim Berners-Lee.

Zajímavé je, že právě objektově orientovaná aplikační vrstva operačního systému NeXTSTEP byla poměrně často napodobována ostatními společnostmi, které produkovaly operační systémy s grafickým uživatelským rozhraním. Z těch známějších systémů se jednalo například o systém Taligent firem Apple (mělo se jednat o nástupce Mac OS), HP a IBM (tato firma měla velké zkušenosti s objektově orientovaným přístupem díky vývoji VisualAge for Smalltalk), ale taktéž o sice často citovaný, ale nikdy nedokončený systém Cairo firmy Microsoft. Dnes je podobný přístup použit jak v Qt, tak i v GTK++, i když zde je patrný mnohem větší vliv programovacích jazyků C a C++. Jedná se například o rozlišování typů objektů již v době překladu a nikoli až v době běhu programu, což vyžaduje změnu stylu programování i odlišný způsob návrhu aplikačního programového rozhraní (API).

Obrázek 6: První grafický webový prohlížeč na světě (WorldWideWeb) z roku 1991 běžící na systému NeXTSTEP.

3. Základní informace o programovacím jazyku PostScript

Již v úvodní kapitole tohoto článku jsme si řekli, že součástí operačního systému NeXTSTEP je i Display PostScript, což je varianta programovacího jazyka PostScript firmy Adobe, který byl rozšířen o některé funkce nutné pro vytváření grafického uživatelského rozhraní. Nejprve si velmi stručně popíšeme základní vlastnosti jazyka PostScript a poté si řekneme, jaké změny bylo nutné v tomto jazyku provést, aby byl využitelný při práci s GUI. Původně byl PostScriptu navržen jako specializovaný jazyk určený primárně především pro popis tiskových stránek, které jsou určeny k tisku na postscriptové tiskárně nebo osvitové jednotce, popř. k převodu tiskové stránky na bitmapový obrázek určený pro tisk na „hloupějších“ tiskárnách (jedná se o GDI tiskárny, tiskárny s konkurenčním jazykem PCL, v minulosti též jehličkové tiskárny). Později se možnosti PostScriptu rozšířily, neboť vznikly specializované programy (viewery) umožňující zobrazit tiskové stránky na obrazovce počítače. Jedná se například o program GhostView používaný společně s Ghostscriptem.

Obrázek 7: Další pohled na grafické uživatelské rozhraní NeXTSTEPu.

Kromě toho může jazyk PostScript (především jeho varianta zapouzdřený PostScript – EPS) sloužit i jako metaformát určený pro přenos grafických informací mezi různými aplikacemi a operačními systémy (slovem „metaformát“ je v tomto kontextu myšlen souborový formát, ve kterém je možné ukládat jak vektorovou kresbu, tak i bitmapovou, tj. rastrovou grafiku). Na rozdíl od většiny ostatních značkovacích jazyků i datových formátů určených pro popis tiskových stránek (jmenujme například v minulosti poměrně často používaný PCL určený pro laserové tiskárny firmy HP či formát HP-GL určený především pro plottery) je grafickou informaci možné v PostScriptu popsat plnohodnotným programovým kódem s využitím proměnných, řídicích struktur, možností definice nových slov (ty jsou obdobou procedur a maker), proměnných, slovníků apod. I když se to v mnoha materiálech příliš nezdůrazňuje, je PostScript turingovsky kompletním jazykem, tj. má stejnou vyjadřovací schopnost, jako běžné programovací jazyky (a ty mají stejnou vyjadřovací schopnost, jako Turingův stroj).

Obrázek 8: Grafické uživatelské rozhraní NeXTSTEPu zůstalo z velké míry zachováno ve správci oken Window Maker (zde ve variantě pro Linux – Window Maker na Asus EEE).

Program napsaný v PostScriptu existuje v čitelné podobě ve formě (skoro)textového souboru, který má většinou příponu .ps nebo .eps (zapouzdřený PostScript). V těchto souborech mohou být uložena i binární data fontů, vložených bitmap apod., proto mohou nastat problémy při ruční editaci souboru v těch textových editorech, které do souboru některé ne-alfanumerické znaky přidávají, nebo naopak ubírají. Program pro popis tiskové stránky může být v PostScriptu napsán velmi čitelně, nicméně prakticky všechny aplikace, které PostScriptový soubor generují, produkují pro člověka nečitelný kód – prohlédněte si například PostScriptový výstup z  TEXu (generovaný většinou přes dvips, ale zde je nečitelnost dána i častou aplikací kerningu) nebo výstup z MS Wordu (obdobou prakticky nečitelného výstupu jsou i mnohé WYSIWYG editory pro HTML či XHTML, které také neprodukují zrovna čistý a čitelný HTML kód).

Obrázek 9: Další screenshot pracovní plochy počítače s běžícím správcem oken Window Maker.

Na PostScriptu je založeno velké množství dalších aplikací. Kromě již zmíněných programových prohlížečů (GhostView, KGhostView) a dalších podobných komerčních programů i prohlížečů šířených pod svobodnými licencemi, jsou to především tiskové programy (poněkud nesprávně nazývané RIPy – Raster Image Processor(s)), které mohou provádět konverzi PostScriptového souboru na bitmapy, jež se mají zobrazit či vytisknout. Tyto konverzní programy nejsou vlastně nic jiného než plnohodnotné interpretry programovacího jazyka PostScript, které postupně zadaný program vykonávají a podle volaných grafických funkcí mění barvu jednotlivých pixelů výsledné bitmapy. PostScriptové tiskárny a osvitové jednotky taktéž obsahují interpretr PostScriptu (RIP), který skládá jednotlivé stránky a postupně je tiskne. Na některých tiskárnách jde také ovládat zabudovaný displej a klávesničku a psát pomocí příkazů PostScriptu humorné hlášky obsluze.

4. Kreslení v PostScriptu s využitím cest a fontů

Patrně nejmocnější vlastností PostScriptu je jeho schopnost práce s takzvanými cestami (path(s)). Ty byly díky své univerzalitě později převzaty i do dalších grafických formátů, například SVG – Scalable Vector Graphics, na jejichž vývoji se taktéž podílela firma Adobe (vlastník licence PostScriptu). Každá cesta se skládá z otevřených nebo uzavřených křivek, dokonce je možné převádět jednotlivé znaky na křivky. Cesta má zadané základní vlastnosti, jako je typ čáry, výplňový vzorek, způsob zakončení a barvu (ta existuje pouze u novějších verzí PostScriptu – konkrétně od Levelu 2). Pomocí uzavřených cest lze také ořezávat část obrázku a cesty současně slouží pro detekci pozice kurzoru v dále popsaném Display PostScriptu. Parametry jednotlivých křivek, ze kterých je cesta složena, se ukládají na datový zásobník a příslušný příkaz (moveto, lineto, curveto) si ze zásobníku automaticky vybere tolik souřadnic, kolik jich pro svou činnost potřebuje. Vlastní vykreslení (rasterizace) cesty se provádí pomocí slova stroke.

Obrázek 10: Blokové schéma cvičného mikroprocesoru, které jsme používali při popisu funkce ALU a řadiče v paralelně běžícím seriálu o architekturách počítačů. Toto schéma bylo nakresleno v aplikaci Open Office.org Draw (důvod, proč je tento obrázek zařazen do tohoto článku, se dozvíte o několik centimetrů níže :-).

V následující tabulce je vypsáno sedm základních příkazů pro práci s cestami:

Příkaz Význam
newpath vytvoření nové cesty, která tak nenavazuje na cestu předchozí
moveto přesun aktivního bodu na zadané absolutní souřadnice bez kreslení
lineto přesun aktivního bodu na zadané absolutní souřadnice s kreslením
rmoveto přesun aktivního bodu na zadané relativní souřadnice bez kreslení
rlineto přesun aktivního bodu na zadané relativní souřadnice s kreslením
closepath uzavření cesty, poslední bod je spojen s bodem prvním
stroke vykreslení cesty nastaveným stylem (implicitně vlasová čára)

Obrázek 11: Část PostScriptového souboru s obrázkem výše zobrazeného blokového schématu cvičného mikroprocesoru. Za povšimnutí stojí zejména způsob definice nových slov (funkcí), například l = lineto, které vedou ke zkrácení výsledného souboru.

Při kreslení, tj. zadávání souřadnic pro příkazy typu moveto, lineto atd. se používá délková jednotka zvaná typografický bod (point), jehož délka je rovna 1/72 palce. Pojem „typografický bod“ je poněkud matoucí, protože existuje více vzájemně odlišných stejně pojmenovaných délkových jednotek a o jejich významu se typografové mnohdy poměrně vášnivě přou (vyplývá to z faktu, že kolébkou typografie je sice Evropa, ale DTP vzniklo a bylo nejvíce rozvinuto v USA). Faktem ovšem zůstává, že PostScript (a zdaleka nejenom on, povšimněte si způsobu zadávání velikosti písma v mnoha programech – „palcové titulky“ jsou sázeny 72bodovým fontem) považuje za svou jednotku právě 1/72 palce, tedy přibližně 0,3527 milimetru (navíc i původní Macintosh měl rozlišení obrazovky upraveno tak, aby se dobře počítalo s touto délkou). To však v žádném případě neznamená, že by jeden typografický bod byl tou nejmenší délkovou jednotkou, kterou je možné v PostScriptu použít. Norma předepisuje, že se délky mohou zapisovat i pomocí čísel s plovoucí řádovou čárkou, požadovaná přesnost je minimálně čtyři desetinná místa (přesností se tedy v tomto ohledu blížíme i k legendárnímu „superpřesnému“ TEXu).

Ukažme si nyní velmi jednoduchý příklad, který pomocí osmice úseček vykreslí domeček „jednou čarou“ Příklad (který je mimochodem plnohodnotným PostScriptovým programem!) nejdříve vytvoří novou cestu příkazem newpath, posléze přejde do počátečního bodu příkazem moveto a následně s využitím příkazu lineto vykreslí zbytek cesty složený z na sebe navazujících úseček. Nakonec se příkazem stroke cesta vykreslí (rasterizuje) a interpretr PostScriptu o cestě zapomene veškeré další údaje. Poslední příkaz showpage zajistí vykreslení či vytištění celé stránky na obrazovku či tiskárnu (v případě EPS by však tento příkaz být uveden naopak nesměl – to si můžete vyzkoušet importem tohoto příkladu například do některého z vektorových editorů):

% Demonstracni priklad na vykresleni domecku
% pomoci osmi na sebe navazujicich usecek.
 
newpath
100 100 moveto
400 100 lineto
100 400 lineto
100 100 lineto
400 400 lineto
100 400 lineto
250 550 lineto
400 400 lineto
400 100 lineto
 
% rasterizace cesty
stroke
 
% vykresleni cele stranky
showpage

Obrázek 12: První demonstrační příklad zobrazený v softwarovém prohlížeči PostScriptu.

5. Bézierovy křivky a fonty v PostScriptu

Součástí cest v PostScriptu mohou být i Bézierovy křivky. Vzhledem k tomu, že tyto křivky navazují na již nakreslené segmenty cesty, znamená to, že se při jejich specifikaci zadávají pouze tři body: dva body řídicí a jeden koncový bod. Zbývající koncový bod je tvořen bodem, kterým cesta doposud končila. Je to podobné, jako při přidávání úseček do cest – také jsme specifikovali pouze druhý koncový bod úsečky, první koncový bod nebylo zapotřebí zadávat (viz předchozí demonstrační příklad). Křivka je do aktuálně vytvářené cesty přidána příkazem curveto. Tento příkaz si při svém spuštění (zavolání) vyzvedne ze zásobníku souřadnice tří bodů, vytvoří křivku (většinou ji ihned převede na sadu úseček – to ovšem záleží na konkrétní implementaci SW nebo HW RIPu) a přidá takto rozloženou křivku do cesty. Při převodu Bézierovy křivky na úsečky se křivka rekurzivně dělí až do okamžiku, kdy je rozdíl mezi skutečným průběhem křivky a její aproximací menší než hodnota plochosti (flatness). Ukažme si vše na jednoduchém demonstračním příkladu:

% Demonstracni priklad na vykresleni sady Bezierovych krivek.
 
% prvni krivka
newpath
 50 700
moveto
 50 800
150 800
150 700
curveto
% rasterizace cesty
stroke
 
% druha krivka
newpath
 50 550
moveto
100 650
100 650
150 550
curveto
% rasterizace cesty
stroke
 
% treti krivka
newpath
 50 400
moveto
125 500
 75 500
150 400
curveto
% rasterizace cesty
stroke
 
% ctvrta krivka
newpath
 50 250
moveto
150 350
 50 350
150 250
curveto
% rasterizace cesty
stroke
 
% pata krivka (se smyckou)
newpath
 75 100
moveto
150 200
 50 200
125 100
curveto
% rasterizace cesty
stroke
 
% cesta v prave casti papiru
newpath
200 800
moveto
% zacneme useckou
400 800
lineto
% a hladce navazeme krivkou
600 800
600 700
400 700
curveto
200 700
200 600
400 550
curveto
600 500
600 450
400 400
curveto
200 350
200 450
400 450
curveto
% hladce navazeme useckou
500 450
lineto
% oblouk - ridici body jsou shodne!
550 450
550 450
550 400
curveto
% opet hladce navazeme useckou
550 200
lineto
% rasterizace cesty
stroke
 
% vykresleni cele stranky
showpage

Obrázek 13: Druhý demonstrační příklad zobrazený v softwarovém prohlížeči PostScriptu.

Nedílnou součástí PostScriptu je i práce s fonty. Systém používající PostScript (prohlížeč, RIP v tiskárně, systémová knihovna operačního systému NeXTSTEP…) může používat více různých typů fontů. Většinou se jedná o fonty, v nichž jsou jednotlivé znaky popsány svým (vektorovým) obrysem, může se však jednat i o fonty rastrové (bitmapové). Dále popsaný Display PostScript navíc obsahuje i podporu pro rastrové fonty s rozlišením shodným s rozlišením obrazovky, které se vykreslují mnohem rychleji než písma zadaná svým obrysem. Práce s fonty je v PostScriptu velmi jednoduchá, což je ukázáno na následujícím demonstračním příkladu (důvod pro tuto jednoduchost je zřejmý – prvotním úkolem PostScriptu byla tvorba sice složitých dokumentů, které se však stále skládaly především z textu). Ve zdrojovém kódu třetího demonstračního příkladu si povšimněte, jakým způsobem je nejdříve nastaven počáteční bod vykreslovaného textu a jak je text vykreslený příkazem show zapsán do kulatých závorek:

% Demonstracni priklad na pouziti fontu.
 
% podkladovy text - musi byt uveden jako prvni
 
% vyhledani fontu
/Helvetica findfont
220 scalefont
setfont
200 350 moveto
0.8 0.8 1.0 setrgbcolor
(42) show
 
% ostatni text je zobrazen cernou barvou
 
0 0 0 setrgbcolor
 
/Helvetica findfont
40 scalefont
setfont
200 300 moveto
(Hello world!) show
 
/Times-Roman findfont
40 scalefont
setfont
200 350 moveto
(Hello world!) show
 
/Bookman findfont
40 scalefont
setfont
200 400 moveto
(Hello world!) show
 
/Palatino findfont
40 scalefont
setfont
200 450 moveto
(Hello world!) show
 
/Zapf-Chancery findfont
40 scalefont
setfont
200 500 moveto
(Hello world!) show
 
% vykresleni cele stranky
showpage

Obrázek 14: Třetí demonstrační příklad zobrazený v softwarovém prohlížeči PostScriptu.

6. Zásobníkový programovací jazyk a tvorba nových slov (funkcí)

Kromě „pouhého“ kreslení je však možné v PostScriptu psát i plnohodnotné programy. Programovací jazyk PostScript je, podobně jako programovací jazyk Forth či tradiční unixová utilita dc, postavený nad abstraktním (virtuálním) několikazásob­níkovým procesorem. Z tohoto důvodu se při programování v PostScriptu nevyhneme častým manipulacím se zásobníky, zejména se zásobníkem operandů. Tyto manipulace se buď provádí pomocí explicitně zadaných příkazů (například duplikace hodnoty uložené na zásobníku pomocí operátoru dup) nebo implicitními operacemi (například při provádění matematických výpočtů nebo při volání vestavěných funkcí). Mezi příkazy, které se zásobníkem manipulují implicitně patří již dříve popsané funkce, jakou je moveto, která ze zásobníku přečte a posléze odstraní dva číselné parametry představující pozici bodu v rovině.

Obrázek 15: Základní operace s abstraktním datovým typem zásobník (stack).

Zásobníky jsou v PostScriptu použity z několika důvodů. Asi nejvýznamnějším důvodem je to, že se „zásobníkový kód“ velmi jednoduše a přitom rychle interpretuje. Ostatně mnoho abstraktních (virtuálních) procesorů je právě z tohoto důvodu postaveno na zásobnících; typickým příkladem je virtuální zdroj jazyka Java (JVM) či Pythonu. Nenechte se zmást paměťovou náročností Javy – příčina jejích mnohdy obrovských paměťových nároků netkví v zásobníkovém kódu (právě naopak), ale v tom, že se pro každý i sebemenší javovský program načítá prakticky celé běhové prostředí Javy s několika tisíci třídami a rozhraními a že i krátké programy manipulují se stovkami a tisíci objekty. Ale například Java Kilobyte Machine resp.  KVM běží, kromě PDA a mobilních telefonů, i na stařičkém ZX Spectru! Další příčinou použití zásobníků v PostScriptu je unifikace všech operací. Zatímco se v běžné matematice vyskytují všechny tři zápisy matematických výrazů (prefixový, infixový i postfixový) a je definitoricky stanovena priorita některých operátorů, PostScript používá všude pouze postfixový zápis.

Nepřímo s tím souvisí i způsob ukládání parametrů na zásobník před voláním funkcí a možnost návratu více hodnot z funkce (použito například při manipulaci s transformačními maticemi). Třetí příčinou použití zásobníků v PostScriptu je poměrně značná obliba Forthu v době jeho návrhu. Ostatně volba programovacího jazyka na základě jeho oblíbenosti také není ničím novým – stačí se podívat na historii COBOLu či Javy. Nicméně pro mnoho programátorů bylo použití postfixové notace a zásobníků poměrně komplikované, což vedlo ke vzniku překladače (či spíše transformátoru) z jazyka C do PostScriptu (a v kontextu tohoto článku je zajímavé, že tento překladač vznikl právě pro operační systém NeXTSTEP).

Důležitou součástí PostScriptu, která usnadňuje modularizaci v něm psaných programů, je možnost vytváření nových slov (funkcí) pomocí příkazu def. V následujícím demonstračním programu je ukázáno, jak lze pomocí nových slov m, lc atd. zkrátit soubor s jednoduchým obrázkem:

/m {moveto} def
/l {lineto} def
/c {curveto} def
/n {newpath} def
/s {stroke} def
/lc {setlinecap} def
/lj {setlinejoin} def
5.0 setlinewidth
0 lc
0 lj n 50 700 m 150 800 l 50 800 l 150 700 l s
1 lj n 50 550 m 150 650 l 50 650 l 150 550 l s
2 lj n 50 400 m 150 500 l 50 500 l 150 400 l s
n 50 250 m 150 350 50 350 150 250 c s
1 lc
0 lj n 250 700 m 350 800 l 250 800 l 350 700 l s
1 lj n 250 550 m 350 650 l 250 650 l 350 550 l s
2 lj n 250 400 m 350 500 l 250 500 l 350 400 l s
n 250 250 m 400 350 200 350 350 250 c s
2 lc
0 lj n 450 700 m 550 800 l 450 800 l 550 700 l s
1 lj n 450 550 m 550 650 l 450 650 l 550 550 l s
2 lj n 450 400 m 550 500 l 450 500 l 550 400 l s
n 500 250 m 600 350 400 350 500 250 c s
showpage

7. Řídicí příkazy (podmínky a programové smyčky)

Prakticky jakýkoli programovací jazyk, který má být reálně použitelný i pro tvorbu složitějších programů, než jednoduchých maker či prostých několikařádkových seznamů příkazů, které se mají postupně provést, obsahuje některou z technologií určených pro řízení běhu programu. Tato technologie je typicky implementovaná ve formě zavedených a takřka univerzálně pojmenovaných strukturovaných příkazů typu „if-then-else“ (resp. pouze příkazu „if-then“ neobsahujícího větev „else“) popř. příkazů typu „switch-case“ (což je ve své podstatě pouze jiná podoba rozeskoků). Tyto příkazy jsou v různé syntaktické podobě obsaženy prakticky ve všech programovacích jazycích pocházejících z algolské větve vývoje, včetně Pascalu, Céčka i Javy a lze je samozřejmě použít i v PostScriptu:

x y gt {(x je vetsi nez y)} if
 
x y lt
    {(x je mensi nez y)}
    {(y je mensi nebo rovno x)}
ifelse

Programovací jazyk PostScript obsahuje i několik operátorů, pomocí kterých je možné sestrojit programové smyčky, tj. opakující se části programového kódu. Z praktických důvodů se v programovacích jazycích vyskytují především dva typy smyček: počítané a nepočítané smyčky (popř. smyčky typu „for each“, které přebírají většinu dobrých vlastností smyček počítaných, přičemž tyto smyčky rozšiřují iterování přes pole, seznamy, n-tice či slovníky). PostScript obsahuje z počítaných smyček smyčku typu repeat a smyčku typu for:

10 {(tato smyčka proběhne desetkrát)} repeat

Příklady použití smyčky typu for:

1 1 10 {} for     % na zásobník se uloží číselná sekvence 1 2 3 4 5 6 7 8 9 10
0 2 10 {} for     % na zásobník se uloží číselná sekvence 0 2 4 6 8 10
10 1 0 {} for     % tato smyčka neproběhne ani jedenkrát
0 -1 10 {} for    % ani tato smyčka nebude spuštěna
0 1 1 4 {add} for % provede se součet 0+1+2+3+4=10
3 -.5 1 { } for   % na zásobník se uloží číselná sekvence 3.0 2.5 2.0 1.5 1.0

Následuje nepatrně složitější příklad využívající počítanou smyčku typu for pro vykreslení jednoduchého obrázku složeného z několika úseček. V těle smyčky je využito hodnoty jejího počitadla pro výpočet koncových souřadnic vykreslovaných úseček. Každá úsečka tvoří samostatnou cestu, ale bylo by možné vytvořit i cestu jedinou, složenou z na sebe NEnavazujících částí. Podobným způsobem je možné vykreslit například i pravidelnou mřížku, logaritmickou mřížku, horizontální či vertikální pravítko apod. – to jsou operace, které se v prakticky všech vektorových editorech tvoří poměrně složitě a přitom mohou být v mnoha případech užitečné.

50 10 400 {    % inicializace smycky for
    newpath    % vytvoreni nove cesty
        % instrukce   zasobnik
        dup         % i i
        50          % i i 50
        moveto      % i        - moveto si vzala souradnici (i, 50)
        400         % i 400
        exch        % 400 i
        lineto      % --       - lineto si vzala souradnici (400, i)
    stroke     % rasterizace cesty
} for
showpage       % a vykresleni cele stranky

Obrázek 16: Výsledek zobrazení PostScriptového souboru obsahujícího výše uvedený kód s počítanou smyčkou typu „for“.

Zcela univerzálním typem smyčky v PostScriptu je nepočítaná smyčka typu loop. Ta je již ze své podstaty smyčkou nekonečnou, tj. ukončení smyčky je nutné explicitně provést pomocí příkazu exit či stop. Příkazy exit a stop se od sebe odlišují především tím, že se po zavolání příkazu exit provede automatický úklid zásobníku tak, aby na něm byly uloženy pouze ty hodnoty, které se zde nacházely před inicializací a spuštěním smyčky, zatímco příkaz exit pouze smyčku ukončí a žádné manipulace se zásobníkem neprovádí. Vzhledem k tomu, že smyčka typu loop nemodifikuje obsah zásobníku operandů (tj. neukládá zde hodnotu počitadla ani nepotřebuje žádné inicializační hodnoty), mají v tomto případě příkazy exit a stop stejný význam (u dalších smyček to však neplatí, proto se u nich většinou volá pouze příkaz exit).

Obrázek 17: Fraktál vytvořený pomocí níže uvedeného demonstračního příkladu (je vhodné jej spouštět spíše v softwarovém prohlížeči a nikoli na sdílené síťové tiskárně :-)

Abychom si ukázali některé schopnosti PostScriptu a současně i vlastnosti programové smyčky loop, je v následujícím příkladu (jedná se o čtyřřádkovou signaturu) ukázán program, který po svém spuštění na tiskárně nebo v softwarovém prohlížeči po určité době zobrazí složitý dynamický systém (GhostView umí stránku zobrazovat přímo v průběhu vykreslování, na rozdíl od běžné tiskárny :-). Celý program má i s dvojicí poznámek délku pouze 296 bajtů, zatímco výsledný (RIPovaný) PNG soubor celých 164 kB. Navíc samozřejmě nelze výsledný bitmapový obrázek zvětšovat beze ztráty kvality:

/d{def}def/a{add}d/s{sub}d/u{usertime}d % Alun Jones, IBS, UW Aberystwyth
/x 0 d/y 0 d 9 9 scale 35 47 translate/b u d .1 setlinewidth{u b s 6e4 gt
{exit}if/x x 4 a d/v 1 x s d/x y 2 x mul 3 s abs sqrt x 0 lt{neg}if a d/y
v d x y moveto .1 0 rlineto stroke}loop showpage% You may need %!PS-Adobe

Obrázek 18: Předchozí demonstrační příklad (signatura) přepsaný do čitelnějšího kódu.

8. Display PostScript – použití PostScriptu při práci s obrazovkou (nejenom) v systému NeXTSTEP

V předchozích pěti kapitolách jsme se stručně seznámili s programovacím jazykem PostScript a v některých odstavcích jsme se taktéž zmínili o určitých specifických vlastnostech Display PostScriptu. O co se vlastně v případě Display PostScriptu jedná? Display PostScript, který budeme v dalším textu označovat zkratkou DSP, byl navržen firmou Adobe pro práci s vektorovou i bitmapovou grafikou na obrazovkách i při tvorbě grafického uživatelského rozhraní. DSP byl použit na některých systémech vyvíjených firmou Xerox (šlo o jednu z posledních významných počinů této společnosti v oblasti grafických uživatelských rozhraní) a především dnes popisovaným operačním systémem NeXTSTEP. DSP se sestává z více částí, především z upraveného interpretru PostScriptu a taktéž z rozhraní určeného pro programovací jazyk C (Objective-C), které zpřístupňuje základní funkcionalitu DSP aplikacím. Toto rozhraní se nazývá pswrap.

Důležité je, že obě části DSP, tj. jak interpret PostScriptu, tak i rozhraní pro další programovací jazyky, jsou zcela nezávislé na parametrech grafického systému, tj. na rozlišení obrazovky či na počtu zobrazitelných barev. V DSP je navíc implementováno pouze vykreslování do již existujících oken, což mj. znamená, že tato okna musí být vytvořena jinými prostředky, ať již v rámci technologie použité v operačním systému NeXTSTEP nebo (především na PC či grafických stanicích) systémem oken X (X Window System). Jinými slovy – DSP se vůbec nestará o to, jakým způsobem jsou okna vytvořena ani jak s nimi uživatel manipuluje. Na následujícím obrázku je naznačeno, jakým způsobem lze DSP začlenit do dnes standardního desktopového systému s X klienty a X servery. Aby DSP mohl splnit svoji roli při práci s obrazovkou i při tvorbě grafického uživatelského rozhraní, bylo nutné v několika ohledech rozšířit jeho funkcionalitu.

Obrázek 19: Začlenění Display PostScriptu do systému NeXTSTEP.

Vzhledem k některým rozdílům mezi tiskárnami a obrazovkami (především se jedná o řádový rozdíl v rozlišení) se v DSP rozšířila podpora pro bitmapové fonty optimalizované pro aktuálně používané rozlišení obrazovky. Zatímco obrysové fonty mají nespornou výhodu v tom, že je lze prakticky beze ztráty kvality zvětšovat a v určité míře zmenšovat, je u nízkých rozlišení (obrazovky monitorů) a typických velikostí písma 9 až 12 bodů nutné provádět ruční optimalizaci vykreslovaných znaků takovým způsobem, aby například tloušťka svislých čar byla shodná (asi by nebylo pěkné vidět například malé „m“ vykreslené tak, že krajní nožičky budou mít šířku dvou pixelů a prostřední nožička pouze jednopixelovou tloušťku). V DSP se pro tento účel používají bitmapová písma se znaky definovanými pro každou velikost písma zvlášť (zvětšování a zmenšování bitmap by v tomto případě vedlo k velké degradaci kvality písma).

U obrazovkových bitmapových fontů má navíc každý znak přesně definovanou šířku specifikovanou v celočíselných násobcích pixelů a současně i šířku zadanou v typografických bodech. To má svůj význam, protože bitmapové znaky je nutné vykreslovat jako skutečné bitmapy, což však může vést k tomu, že text zobrazený na obrazovce by neodpovídal textu vytištěnému na tiskárně. Teoreticky totiž u každého bitmapového znaku může kvůli zaokrouhlení jeho šířky na celé pixely dojít k chybě o velikosti až poloviny pixelu (znak je potom při vykreslení o jeden pixel širší či naopak užší), což například při 80 znacích na jedné řádce může vést až ke kumulaci chyby o velikosti několika desítek pixelů! DSP tento problém řeší tak, že jsou znaky sice v rámci jednoho slova usazovány na celočíselné souřadnice, ale souřadnice následujícího slova jsou již počítány přesně – jako součet přesných šířek znaků předchozího slova spolu se započtením podřezávání atd. (DSP má tedy dvojí současně používaný souřadný systém).

Dále je v DSP upraven subsystém sloužící pro dithering a halftoning, tj. zdánlivého zvyšování počtu současně zobrazitelných barev kombinací barev sousedních pixelů. Algoritmy ditheringu a halftoningu použité při tisku totiž mohou na obrazovce tvořit nepříjemné vizuální chyby, především v těch případech, kdy se obsah okna posouvá (scrolluje). Programátor může v tomto případě určit pozici bodu, od kterého se vzorek vznikající halftoningem začíná vykreslovat.

Obrázek 20: Display PostScript při použití spolu se systémem oken X.

Výše uvedené změny či přesněji řečeno rozšíření DSP spočívají zejména v úpravě vykreslovacích algoritmů s ohledem na jinou technologii zobrazení dat na obrazovce oproti tisku na tiskárnám. Ovšem důležitější jsou změny související s okny a GUI. Především se jedná o komunikaci se správcem oken, díky níž je například možné zajistit, aby se překreslovala pouze část celé kreslicí plochy – například při animaci stisku tlačítka na obrazovce zajisté není nutné překreslovat celou pracovní plochu aplikace, zejména v tom případě, že je viditelná pouze malá část této plochy. Z tohoto důvodu lze definovat oblast, která se má překreslit, přičemž tato oblast je definována pomocí obecné cesty (!), nikoli pouze obdélníku, jak je tomu v jiných systémech.

S touto novou funkcí souvisí i další změna – v klasickém PostScriptu je možné pomocí slova def vytvářet objekty, které jsou pojmenované. Může se například jednat o funkci (slovo), které slouží k vykreslení již zmíněného tlačítka s nápisem. Ovšem pojmenování objektů pomocí řetězců je náročné na technické prostředky počítače (rychlost procesoru a kapacitu operační paměti) a navíc nevhodné při volání postscriptového kódu z céčkových programů. Z tohoto důvodu lze v DSP nově vytvářeným objektům přiřadit celočíselný identifikátor, ke kterému lze přistupovat jak z vlastního PostScriptu, tak i z céčkového/Ob­jective-C programu.

Obrázek 21: Struktura aplikace využívající Display PostScript a knihovny systému oken X.

Při tisku (spuštění) postscriptového programu na tiskárně či v programovém RIPu je celé vykreslení spuštěno jako jediný proces, tj. tiskárna či SW RIP si musí vytvořit pouze jednu transformační matici, jednu paměťovou oblast pro proměnné a uživatelské funkce, jeden zásobník operandů atd. Toto však v žádném případě neplatí v DSP, kdy je každé okno vykreslováno nezávisle na ostatních oknech a to dokonce ve stejném okamžiku. Z tohoto důvodu zavádí DSP podporu pro souběžnou práci většího množství postscriptových procesů, a tato podpora je dokonce dotažena do té míry, že jednotlivé postscriptové procesy (zvané kontexty) spolu mohou v případě potřeby komunikovat, sdílet si proměnné nebo se navzájem synchronizovat. Samozřejmě je možné nastavit míru izolace jednotlivých procesů, protože je nepřípustné, aby jedna špatně napsaná aplikace blokovala všechny ostatní programy používající GUI. Pro účely vytváření nových postscriptových procesů byla v DSP nadefinována nová slova, jejichž význam je většinou zřejmý: fork, join, detach, currentcontext, wait, monitor, yield, lock, condition.

UX DAy - tip 2

Poslední nová vlastnost zavedená v rámci DSP souvisí se zpětnou vazbou mezi grafickým oknem a aplikací, které toto okno náleží. Aplikace v jednom směru provádí vykreslování pomocí DSP do okna, ovšem v opačném směru musí mít možnost zjistit, na kterém místě v okně se nachází kurzor myši. Na zcela nejnižší úrovni to samozřejmě není prakticky žádný problém, protože správce oken vrátí souřadnice myši v okně (x,y). Tato informace je však nedostačující v případě složitějších aplikací, kdy je například nutné zjistit, zda uživatel klikl na vykreslené tlačítko, obrázek vedle tlačítka, na nějaké zobrazené slovo atd.

Samozřejmě je možné si přímo v aplikaci vést „evidenci“ tvarů všech objektů vykreslených v okně, ovšem to je zbytečně pracné. Namísto toho je v DSP zavedena podpora pro takzvanou hit detection (detekci zásahu), jejíž princip je v podstatě velmi jednoduchý – lze testovat, zda by byl zvolený bod (většinou přečtené souřadnice kurzoru myši) vykreslený nějakou kreslicí či vyplňovací operací, tj. zda leží na zvolené cestě či uvnitř vyplněné cesty. Totéž je možné zjistit pro definované okolí tohoto bodu (jedná se většinou o malou kružnici, čtverec či diamant se středem v tomto bodě). Okolí bodu se používá především pro „chytání“ koncových bodů úseček ve vektorových grafických editorech či CAD programech, méně často již pro uzavřené tvary.

9. Odkazy na další informační zdroje

  1. Adobe Systems: PostScript Language Reference Manual, The Red Book,
    Adobe Systems Incorporated, 2nd ed., Addison Wesley 1990.
  2. Adobe Type 1 Font Format (včetně ukázek s použitím smyček),
    Addison-Wesley
  3. PostScript Language Program Design,
    Addison-Wesley 1990, ISBN 0–201–14396–8
  4. PostScript Language Reference Manual,
    Addison-Wesley 1990, ISBN 0–201–18127–4
  5. PostScript Language Tutorial and Cookbook,
    Addison-Wesley 1990, ISBN 0–201–10179–3
  6. Display PostScript
    http://c2.com/cgi/wi­ki?DisplayPos­tscript
  7. Display PostScript
    http://en.wiki­pedia.org/wiki/Dis­play_PostScript
  8. Network Extensible Window System
    http://c2.com/cgi/wi­ki?NetworkExten­sibleWindowSys­tem
  9. PostScript fractals,
    http://www.pvv­.ntnu.no/~ander­sr/fractal/Pos­tScript.html
  10. Fractal generation,
    http://www.chez­.com/emarsden/dow­nloads/
  11. Paul Bourke: PostScript Tutorial,
    http://local.was­p.uwa.edu.au/~pbou­rke/dataformat­s/postscript/
  12. A First Guide to PostScript,
    http://www.ta­ilrecursive.or­g/postscript/pos­tscript.html
  13. A History of the GUI (6) – More GUIs of the 1980s
    http://arstechni­ca.com/old/con­tent/2005/05/gu­i.ars/6
  14. Chronology of Workstation Computers
    http://www.is­landnet.com/~kpol­sson/workstat/
  15. NeXTSTEP (Wikipedia EN)
    http://en.wiki­pedia.org/wiki/NeX­TSTEP
  16. NeXTSTEP (Wikipedia CS)
    http://cs.wiki­pedia.org/wiki/NeX­TSTEP
  17. NeXT Computers
    http://www.nex­tcomputers.or­g/
  18. The NeXT Computer Historical Site
    http://simson­.net/ref/NeXT/
  19. NeXT Computers Specification
    http://simson­.net/ref/NeXT/spe­cifications.htm
  20. NeXT (Wikipedia EN)
    http://en.wiki­pedia.org/wiki/NeXT
  21. NeXTstation Overview and technical details
    http://lowendmac­.com/next/nex­tstation.html
  22. NeXTstation (Wikipedia EN)
    http://en.wiki­pedia.org/wiki/NeX­Tstation
  23. Window Maker
    http://en.wiki­pedia.org/wiki/Win­dow_maker

Byl pro vás článek přínosný?