- předchozí článek - následující článek - obsah -

Linuxové noviny Únor 1998

PostScript, fonty v UNIXu a tisk z Netscape

Petr Olšák, 10. února 1998

Na diskusním listu linux@muni.cz proběhla (mimo jiné) zmínka o tom, jak zařídit, aby bylo možné tisknout česky z Netscape. Správně tam bylo poznamenáno, že řešení, při kterém se Ghostscriptu předloží pod nesprávným jménem upravené fonty, nelze doporučit. V tomto článečku se pokusím vysvětlit širší souvislosti, které problematika tisku z UNIXu (a tedy i z Linuxu) přináší. Také zmíním podpůrné řešení tisku z Netscape podle pana Petra Macháčka (zařazení filtru do tiskové úlohy), které se zřejmě jeví jako nejrozumější. V současné době asi neexistuje zcela čisté řešení tohoto problému. Naznačím rovněž, jak bych si představoval řešení, které by bylo možné nazvat čistým a jakou práci je k tomu potřeba udělat. Začnu nejprve zevrubným úvodem do problematiky.

Vesměs všechny UNIXové aplikace používají pro tisk v grafickém režimu tiskárny jazyk PostScript. Jedná se o jednoduchý postfixový jazyk vyvinutý firmou Adobe http://www.adobe.com jako standard pro úplný grafický popis tištěné strany prostřednictvím jednoduchých grafických operátorů. Kód PostScriptu je čitelný text jako kód kteréhokoli jiného programovacího jazyka. Tento kód se stává při tisku z aplikace obsahem tiskové úlohy. Úloha se předá přímo tiskárně, pokud tato tiskárna umí PostScriptový kód interpretovat, tj. obsahuje PostScriptový RIP (Raster Image Procesor). Úkolem RIPu je PostScriptové instrukce zpracovat a proměnit v bitovou mapu stránky nebo jiný popis stránky, který přímo navazuje na technologii tisku. Vidíme, že u tiskáren nebo osvitových jednotek s velmi vysokým rozlišením je RIP vestavěný do zařízení nutností. Bitová mapa tištěné strany totiž obsahuje obrovské množství dat, takže je vhodné, aby vznikla až v paměti tiskového zařízení. Z počítače proudí do zařízení podstatně kratší a transparentní PostScriptový kód.

Pokud (levnější) tiskárna neobsahuje zabudovaný PostScriptový RIP, je úkolem tiskového démona lpd zařadit do cesty úlohy filtr, který emuluje RIP přímo v počítači a převede úlohu z PostScriptu do řeči, které rozumí konkrétní cílová tiskárna (například do jazyka PCL). Tímto filtrem bývá většinou Ghostscript, volně dostupný program. Takový program musí obsahovat jednotlivé ovladače všech použitých typů tiskáren. Ovladače tiskáren jsou většinou součástí distribuce Ghostscriptu jako zdrojové moduly. Před kompilací se dá nastavit, které ovladače do výsledného binárního programu zahrnout a které ne. Binární program gs pak při spuštění s parametrem -h vypíše, jaké ovladače jsou v něm zakompilovány. Starost o ovladač tiskárny je tedy v UNIXu vždy záležitostí Ghostscriptu nebo podobného programu. Bohatý sortiment jazyků tiskáren není tedy starostí operačního systému a už vůbec ne aplikace, která tiskovou úlohu generuje. Aplikace má za úkol vygenerovat transparentní PostScriptový kód a tím to pro ni končí.

Poznamenejme, že lze poměrně snadno konfigurovat tiskového démona tak, aby kontroloval první dva znaky tiskové úlohy. Jedná-li se o dvojici "procento, vykřičník", pak to znamená, že úloha obsahuje PostScriptový kód a démon zařadí pro levnější tiskárny (bez samostatného RIPu) filtr realizovaný většinou Ghostscriptem s příslušnými parametry. Nezačíná-li úloha na uvedené dva znaky, pak ji démon předá tiskárně bez interpretace. Taková konfigurace umožňuje tisknout z UNIXu třeba v textovém režimu tiskárny jednoduché textové soubory nebo využít přímo jazyka tiskárny, pokud to náhodou nějaká aplikace umožňuje. Protože UNIXové tiskové servery používáme často i pro úlohy generované z jiných operačních systémů, které se většinou samy starají o ovladače tiskáren a generují úlohy přímo v jazyce tiskáren, je uvedená konfigurace démona vlastně nutností.


 Bookman-Demi
 Bookman-DemiItalic
 Bookman-Light
 Bookman-LightItalic

 Courier
 Courier-Oblique
 Courier-Bold
 Courier-BoldOblique

 AvantGarde-Book
 AvantGarde-BookOblique
 AvantGarde-Demi
 AvantGarde-DemiOblique

 Helvetica
 Helvetica-Oblique
 Helvetica-Bold
 Helvetica-BoldOblique

 Helvetica-Narrow
 Helvetica-Narrow-Oblique
 Helvetica-Narrow-Bold
 Helvetica-Narrow-BoldOblique

 Palatino-Roman
 Palatino-Italic
 Palatino-Bold
 Palatino-BoldItalic

 NewCenturySchlbk-Roman
 NewCenturySchlbk-Italic
 NewCenturySchlbk-Bold
 NewCenturySchlbk-BoldItalic

 Times-Roman
 Times-Italic
 Times-Bold
 Times-BoldItalic

 Symbol

 ZapfChancery-MediumItalic
 ZapfDingbats

Výpis 1: Seznam vestavěných fontů v každém RIPu

PostScriptový RIP pracuje s PostScriptovými fonty. Každý RIP má být podle návrhu firmy Adobe interně vybaven 35 přesně vyjmenovanými základními řezy (viz výpis Seznam vestavěných fontů v každém RIPu). Pokud úloha využívá jiné fonty, je povinností aplikace zařadit PostScriptový popis těchto fontů do tiskové úlohy před prvním použitím fontu. Takovému zařazení fontu do úlohy říkáme download. Textové fonty ze zmíněné sady standardních 35 fontů mají výchozí kódování podle Adobe definované v tzv. StandardEncoding vektoru. Toto kódování neobsahuje plnohodnotné akcentované znaky, ale pouze anglickou abecedu společně s jednotlivými akcenty všech latinkou píšících jazyků. Akcenty jsou tedy zahrnuty pouze jako samostatné znaky. Obsah fontů kódovaných podle StandardEncoding vektoru může čtenář najít například v knize (1) nebo dostupněji v knize (2) v dodatku F.

PostScriptové fonty se distribuují většinou ve formátu Type 1. Specifikace tohoto formátu (3) omezuje použití PostScriptových operátorů k vytvoření grafické podoby znaku jen na některé. Obsahuje také některá další technická omezení, týkající se například parametrů použitých Beziérových křivek. Cílem všech těchto omezení je možnost definovat podmnožinu PostScriptového RIPu, která se specializuje jen na rastrování znaků Type 1 fontů, a přitom pracuje velmi efektivně a rychle. Uživatelé Windows znají takový okleštěný RIP pod jménem ATM (Adobe Type Manager). Uživatelé UNIXu a XFree86 jistě zjistili, že tento speciální RIP je nedílnou součástí jejich grafického rozhraní. Type 1 formát obsahuje navíc specifikaci tzv. hintingu. Tím se myslí soubor instrukcí označujících určité části znaků, které by měly zvláště v nízkém rozlišení podléhat stejnému zaokrouhlování rastrovacího algoritmu. Cílem je, aby například serify jednotlivých písmen i po zaokrouhlení do nízkého rozlišení dopadly pro všechny znaky stejně.

Společnost Microsoft nenavázala na standard podle Adobe a použila jiný formát fontů - TrueType. Ten na rozdíl od Beziérových kubik v Type 1 dovoluje k popisu obrysů použít jen Beziérovy kvadriky. Na druhé straně má TrueType možná poněkud bohatší specifikaci hintingu. Vzhledem k tomu, že obrysy znaků jsou v tomto formátu popsány křivkami odlišného řádu, dochází zákonitě při automatické konverzi z jednoho formátu do druhého ke zkreslení. Toho si musíme být vědomi, pokud kupujeme nový řez. Byl-li řez nativně vyvinut v Type 1 formátu, je po převodu do TrueType horší nejen obrys, ale i možnosti hintingu jsou omezeny. K podobným komplikacím dochází i při převodu v opačném směru. Pokud bychom převod několikrát opakovali, můžeme písmo rovnou vyhodit.

Type 1 fonty se distribuují v souborech s příponou pfb (PostScript Font Binary) nebo pfa (PostScript Font ASCII). Variantu pfa bychom mohli přirovnat výstupu programu uuencode, zatímco varianta pfb je binární a kompaktní. Soubory pfb většinou instalujeme na disk, zatímco formát pfa je nutný při zavedení fontu do tiskové úlohy jako download, protože PostScriptový kód musí být textový. Každá aplikace tedy musí umět převádět z pfb do pfa, chce-li provozovat download. Programy z volně šířeného balíku t1utils převádějí mezi uvedenými formáty (t1ascii, t1binary) a navíc dokáží dešifrovat kód fontu na jednotlivé PostScriptové operátory (t1disasm a t1asm).

S fonty se dodávají též metrické údaje afm (Adobe Font Metric). Na rozdíl od prodávaných popisů tvarů (pfb, pfa) jsou údaje afm většinou volně k dispozici na serverech firmy Adobe a jiných. Soubory afm jsou určeny pro aplikaci, která může na základě informací z nich generovat poněkud sofistikovanější PostScriptový kód. Především se aplikace z afm dozví rozměry znaků potřebné pro výpočet sazby. Také odtud přečte údaje o doporučených hodnotách pro kerningové páry a o ligaturách. Znám jedinou free aplikaci, která dokáže plně využít informace z afm a tou je TeX.

TeX umí dokonce využít fonty podle StandardEncoding vektoru i v textech, kde se vyskytují akcentovaná písmena. V PostScriptovém kódu je v místě výskytu každého akcentovaného písmene automaticky zařazena sada instrukcí, pomocí kterých RIP sestaví akcentovaný znak z jednotlivých elementů (akcentu a písmene). Takové chování je umožněno díky koncepci tzv. virtuálních fontů. Proto TeX dokáže i v plném českém textu využít standardních 35 fontů obsažených v každém PostScriptovém RIPu. Nemusí se tedy v tiskové úloze použít "download". Bohužel, jiné aplikace takovou schopnost nemají.

Aplikace si může v mezích možností PostScriptového fontu sama deklarovat použité kódování. Na PostScriptový font lze totiž pohlížet jen jako na sadu procedur pro vykreslení jednotlivých znaků. Tyto procedury nejsou uspořádané. Uspořádáním názvů těchto procedur do posloupnosti 256 jmen vzniká Encoding vektor. Implicitní Encoding vektor každého fontu může aplikace změnit. Fonty běžně obsahují více procedur, než je uvedeno ve StandardEncoding vektoru. Například ve StandardEncoding vektoru nenajdeme pozici pro znak é, ale vesměs všechny fonty proceduru /ecaron, která vykreslí znak é, obsahují. Textové fonty ze sady vestavěných 35 fontů každého RIPu obsahují procedury pro kresbu všech znaků používaných v západoevropských jazycích. Na výpisu Změna Encoding vektoru podle Netscape je předvedena část PostScriptového kódu, která zavádí jeden ze standardních 35 fontů Times-Roman a před jeho použitím mu vnutí kódování podle ISO8859-1 změnou Encoding vektoru. Přesně takový kód používá pro tisk program Netscape.


 [ /.notdef /.notdef /.notdef /.notdef
 ...
 /ae /ccedilla /egrave 
 /eacute /ecircumflex
 ... %%%              ^^pozice 233
 /ydieresis] /isolatin1encoding exch def

 /F0
    /Times-Roman findfont 
    %%% zavede Times-Roman
    dup length dict begin
	{1 index /FID ne {def} 
	  {pop pop} ifelse} forall
        /Encoding isolatin1encoding def   
	%%% nový Encoding
    currentdict end
 definefont pop
   %%% definuje F0 jako font 
   %%% Times-Roman s novým Encoding
 /f0 { /F0 findfont exch scalefont 
   setfont } bind def
   %%% f0 je makro, které nastaví 
   %%% F0 na uvedené zvětšení

 %%% Analogicky definuje f1 až f7
 %%% pro základní řezy Times a Courier.

 %%% Page 1
 20 20 moveto
 12 f0  %%% Times-Roman 
       %%% ve velikosti 12 bodů
    (J\351je to funguje!) show
 %%  Jéje to funguje! \351 
 %%  oktalově = 233 dekadicky
 showpage

Výpis 2: Změna Encoding vektoru podle Netscape

Kámen úrazu ale je, že standardně dodávané fonty, které najdeme v každém RIPu, neobsahují procedury pro vykreslení všech znaků naší abecedy. Například proceduru /ccaron pro písmeno č bychom ve standardním fontu Times-Roman hledali marně. Netscape toto dilema neřeší a generuje vždy kód podle výpisu Změna Encoding vektoru podle Netscape bez závislosti na tom, jaký je zvolen Document Encoding. To je samozřejmě chyba programu. Pokud tedy máme text WWW stránky v ISO8859-2, pak při tisku dojde k pomíchání kódování.


 /NimbusRomNo9L-Regu	(n021003l.pfb);
 /NimbusRomNo9L-ReguItal	(n021023l.pfb);
 /NimbusRomNo9L-Medi	(n021004l.pfb);
 /NimbusRomNo9L-MediItal	(n021024l.pfb);

 %% Aliasy
 /Times-Roman  /NimbusRomNo9L-Regu    ;
 /Times-Italic /NimbusRomNo9L-ReguItal;
 /Times-Bold   /NimbusRomNo9L-Medi    ;
 /Times-BoldItalic /NimbusRomNo9L-MediItal;

Výpis 3: Soubor Fontmap definující náhradníky Times-Roman

Porozhlédněme se nyní po free softwaru a podívejme se, jaké fonty máme k dispozici. S volně šířeným Ghostscriptem se dodává 32 náhradníků, kteří velmi dobře nahrazují standardních 35 fontů, a přitom jsou free a jsou v Type 1 formátu. Máme tedy k dispozici plnohodnotný softwarový RIP, jako RIPy dodávané v tiskových zařízeních. Všechny fonty, které "Ghostscriptový RIP" má z pohledu tiskové úlohy vestavěny, jsou uvedeny v konfiguračním souboru Fontmap. Část tohoto souboru, týkající se rodiny fontů Times-Roman, vidíme ve výpisu Soubor Fontmap definující náhradníky Times-Roman. Když je například v PostScriptovém kódu řečeno

/Times-Roman findfond 10 scalefont setfont
použije RIP vestavěný font Times-Roman, což podle Fontmap znamená, že se použije soubor n021003l.pfb. Tento font má výchozí kódování StandardEncoding a obsahuje všechny znaky umožňující předefinovat kódování podle ISO8859-1, jak bylo předvedeno ve výpisu Změna Encoding vektoru podle Netscape. Bohužel, písmeno č tam budeme hledat marně.

Porozhlédněme se nyní po Type 1 fontech, které jsou přímo kódovány v ISO8859-2. To je kódování, které používáme pro češtinu v UNIXu a tedy i v Linuxu. Bohužel k dnešnímu dni se mi podařilo najít jedinou sadu takových fontů, sice z ftp://ftp.osb.hu/pub/misc/fonts/local/latin-2. Jedná se o dílo Pétera Soóse a vytvořil je použitím Fontographeru. Pravděpodobně konvertoval běžné fonty dodávané ve Windows ve formátu TrueType a upravil pro ně akcenty. Balík obsahuje obvyklé řezy rodin Ariel, Times a Courier. Tyto fonty jsou z mnoha ohledů špatné, ale je potřeba konstatovat: díky za ně, máme aspoň to.

Především fonty mají poměrně špatný hinting. Všimneme si, že v nižším obrazovkovém rozlišení (po instalaci fontů do X serveru) se například u fontu Ariel propadají písmena a, e pod řádek. Kromě toho mají úplně špatně deklarován svůj Encoding vektor. Všechny názvy znaků v tomto vektoru jsou uvedeny podle ISO8859-1, ačkoli font je v ISO8859-2. Problém předvedu na příkladě. Podle Encoding vektoru fontu (podívejte se do něj pomocí t1disasm) je na pozici 232 název /egrave (\`e), což je v souladu s ISO8859-1. Procedura /egrave ve fontu kupodivu vykreslí znak č, což je v souladu s ISO8859-2. Procedura /ccaron ve fontu vůbec neexistuje. Pokud se aplikace opírá při generování PostScriptového kódu o názvy procedur jednotlivých znaků fontu (což při deklarování vlastního Encoding vektoru dělá), je ztracena a zmatena. Je to tedy velmi hrubá chyba fontu, ale paradoxně díky této chybě existuje cesta, jak tisknout česky z Netscape.

Víme totiž, že Netscape tiskne natvrdo vždy v ISO8859-1 i české stránky. Kdybychom tedy instalovali do Ghostscriptu místo standardního Times-Roman například Soósův ptm2____.pfb, pak by se chyba v Netscape s chybou ve fontu kompenzovaly a výsledkem by byl správně vytištěný český text. Toto řešení ovšem za žádných okolností nedoporučuji. Nahrazením původních fontů z Ghostscriptu Soósovými bychom si zcela zničili "Ghostscriptový RIP", který by od té chvíle nesplňoval očekávané specifikace pro standardních 35 fontů. Je sice pravda, že bychom pak mohli vesele tisknout z Netscape, ale třeba všechny tisky z TeXu, které se opírají o vestavěné PostScriptové fonty, by dopadly tragicky.

Fonty pana Soóse navíc nelze trvale instalovat do RIPů, které jsou zabudovány přímo do tiskáren. Na takových tiskárnách by tedy Netscape stále tiskl češtinu špatně.

Podstatně lepší řešení tisku z Netscape pochází od pana Petra Macháčka. Toto řešení se opírá pouze o standardní fonty, které jsou v každém PostScriptovém RIPu. Uživatel napíše do dialogového boxu pro tisk místo původního lpr -Ptiskarna nově csprint | lpr -Ptiskarna a může se na to dívat jako na tajuplnou sekvenci, kterou mu poradí administrátor a o které dále nebude přemýšlet. Od této chvíle tiskne na všech tiskárnách z Netscape česky. Popíšeme si, jak toto řešení pracuje.

Filtr csprint (nebo jakkoli jinak nazvaný), který si zkopírujeme z adresy http://www.cestina.cz/cestina/pocestovani/unix/WWW/filtr, zavede do generovaného kódu definice českých fontů. Tyto fonty jsou deklarovány jako Type 3 PostScriptové fonty a jednotlivé znaky se čerpají z původních vestavěných fontů. Akcentované znaky jsou definovány jako kompozity.

Nevýhodou tohoto postupu je skutečnost, že pro tisk se do kódu zavádí zbytečně velká hlavička (230 kB) a práce RIPu se zpomalí. Na druhé straně většinou z Netscape tiskneme krátké texty bez nároku na kvalitu (program nepodporuje ani kerning ani vyrovnání podle pravého okraje). Z tohoto pohledu se řešení jeví jako dostačující.

Filtr vytvořený panem Macháčkem by se dal ještě mírně zjednodušit. Všechny znaky, které má čeština společné se sadou ISO8859-1 lze použít přímo a nikoli jako kompozit. Takže /eacute (é) nemusí RIP sestavovat jako /e a /acute, ale stačí použít původní /eacute.

Existuje ještě jedno řešení, které je kombinací obou předchozích. Použije se filtr, který místo Type 3 kompozitních fontů zavede Type 1 fonty pana Soóse jako download. Možná se tím trochu zrychlí práce RIPu, ale velikost záhlaví kódu nezmenšíme. Takže takové řešení je zcela srovnatelné s použitím filtru podle pana Macháčka.

Vidíme, že popsaná řešení jsou provizorní. Lepší časy nastanou, až budou splněny dvě podmínky:

  1. budou k dispozici kvalitní a bezchybné pfb fonty podle ISO8859-2.
  2. Netscape umožní definovat obsah záhlaví generovaného PostScriptového kódu prostřednictvím konfiguračního souboru.
Pak by šlo zanést přímo do tohoto souboru fonty v pfa variantě jako download a generovaný PostScriptový kód českých stránek by nebyl závislý na fontech instalovaných v RIPu. Název zaváděného konfiguračního souboru by přitom mohl záviset na nastaveném Document Encoding, takže by mohlo existovat řešení pro všechny možné případy kódování WWW stránek.

Rovněž by měla existovat souvislost mezi obrazovkovými fonty, které uživatel zvolí pro prohlížení textu a tiskovými fonty. Taková souvislost zatím neexistuje. Je tedy vidět, že problematika tisku je ve stávající verzi Netscape hodně odbytá. Věřím, že uvolnění zdrojových textů Netscape přispěje k rychlé nápravě těchto nedostatků. *

  1. PostScript Language Reference manual
    Adobe Systems Incorporated, Addison-Wesley, 1990
  2. Typografický systém TeX
    Olšák Petr, CSTUG 95
  3. Adobe Type 1 Font Format
    Adobe Systems Incorporated, Addison-Wesley, 1990


- předchozí článek - následující článek - obsah -