Portál AbcLinuxu, 2. května 2024 06:53
U tak složitého systému, jakým je TeX, se občas bohužel stane, že ne vše funguje jak má. V takovém případě uživatelům asi nepostačí jen znalost autorského značkování a musejí se zanořit poněkud do hloubky mezi nánosy všeho možného, co přinesla dlouholetá historie TeXu. V tomto díle seriálu si ukážeme, jak TeX přistupoval a přistupuje ke kódování znaků textových fontů. Aspoň rámcový přehled v této problematice se jistě vyplatí.
Původně Knuth rozhodl, že TeX bude interně pracovat v ASCII kódování. Na 94
viditelných ASCII znaků navázaly pro TeX připravené a zhruba stejně
kódované fonty Computer Modern. Co Knuth neměl na své klávesnici a chtěl
tisknout, na to si připravil řídicí sekvenci. Například \ae
vytisklo æ.
Takovéto znaky Knuth vpravil do zbývajících míst 128znakové tabulky fontů Computer Modern.
Například znaku æ přidělil pozici 26 a řídicí sekvenci \ae
pak deklaroval v makru plainTeX primitivním příkazem \chardef\ae=26
.
Na některé znaky nezbylo ve fontech místo, takže třeba znak paragrafu (§) byl
tištěn makrem \S
, které jej dosti nekoncepčně lovilo z doplňkové
sady matematických fontů. Můžeme k tomu mít dnes výhrady, ale uvědomme si, že
se psal rok 1982.
Další vychytávku Knuth vymyslel pro snadné dosažení střední a dlouhé pomlčky:
dvojice --
nebo trojice ---
se proměnila na odpovídající
pomlčku díky tomu, že byla zanesena v tabulce ligatur fontu Computer Modern.
Analogicky se f a i promění automaticky ve fontu na ligaturu fi.
Implementace pomlček jako ligatur taky není příliš ideální. Na druhé straně je to
ergonomické, účelné a přehledné při psaní zdrojových textů: tyto pomlčky ani
nyní na klávesnici přímo přístupné nejsou.
Pro znaky s akcenty měl Knuth připravena další makra, která sestavovala
akcentovaný znak z komponent (například z háčku a písmene). Takže
„české slovo“ se dalo (a dosud dá) napsat jako \v{c}esk\’e slovo
.
S takovýmto TeXem jsem se poprvé setkal asi v roce 1990 a prohlásil
jsem, že pokud se to má začít používat v češtině, pak takto rozhodně ne.
A chopili jsme se společně s ostatními zájemci o TeX z tehdejšího
Československa práce...
Dnes existují 16bitové modifikace TeXu (XeTeX a LuaTeX), které pracují interně v Unicode a se stejně kódovanými fonty. Ovšem cesta k tomuto stavu byla dlouhá a vedla různými oklikami. Netradičně začnu od konce a popíšu nejprve možnosti, které nabízejí současné 16bitové TeXy.
Je třeba rozlišovat mezi kódováním vstupního souboru (což musí být UTF-8) a interním kódováním 16bitového TeXu (Unicode). Konverzi mezi prvním a druhým světem zajišťuje v TeXu vestavěný input procesor podle jednoduchého pravidla. V TeXu probíhá i opačná konverze zpět do UTF-8 při ukládání informací do textových souborů (například pro opakované načtení při sestavení obsahu). Dlužno podotknout, že input procesor včetně zpětné konverze měl v daleko jednodušší podobě už Knuth ve svém prvním TeXu: řešil tehdy otázku existence dvou kódování anglické abecedy EBCDIC a ASCII s tím, že interně v TeXu předpokládal vždy ASCII i na mašinách, které pracovaly v EBCDIC.
Input procesor konvertující UTF-8 do Unicode (a zpět) je v XeTeXu implementován „natvrdo“, zatímco v LuaTeXu je řešen pomocí Lua skriptu a je tedy modifikovatelný. Na interní kódování TeXu musejí navázat stejně kódované vzory dělení slov jednotlivých jazyků a fonty. V tomto případě tedy vzory dělení slov a fonty musejí být v Unicode.
Při psaní česky nebo slovensky v 16bitovém TeXu jsme nuceni skutečně užít unicodový font, protože znaky české a slovenské abecedy mají v Unicode přidělena čísla často větší než 255. Na druhé straně naši evropští kolegové na západ od nás používající kódovou sadu ISO-8859-1 (francouzi, němci, španělé, atd.) mohou pro svůj jazyk načíst i starší 8bitový font, protože Unicode se ve znacích jejich jazyka shoduje s ISO-8859-1. Nejsou tedy odkázáni na fonty jen ve formátu OpenType. Mají-li nějaký starší oblíbený font v kódování ISO-8859-1, nemají s tím v XeTeXu ani LuaTeXu (na rozdíl od nás) problém.
Zdrojové dokumenty je potřeba pořizovat za použití vhodného ovladače klávesnice
nebo input metody textového editoru. Tím se dá zcela vyhnout původnímu způsobu
pořizování textů, při kterém platilo pravidlo, že co není na klávesnici, na to se
použije řídicí sekvence. Takže při zapnuté české klávesnici píšeme jednoduše česky.
V editoru Emacs je také speciální input metoda, při které uživatel napíše
\ae
a ono se to okamžitě v textovém editoru promění na UTF-8 kód
znaku æ. Nebo zápis ---
Emacs promění v UTF-8 kód dlouhé pomlčky.
Osobně se domnívám, že nic se nemá přehánět. Tento způsob zápisu totiž svádí
používat UTF-8 kódy třeba i v matematických vzorcích. Porovnejte:
$$ \sum_{n=1}^\infty {1\over n^2} = {\pi^2 \over 6} $$ $$ ∑_{n=1}^∞ {1\over n^2} = {π^2 \over 6} $$
Aby druhý řádek fungoval, je potřeba mít použité kódy deklarovány jako
odpovídající matematické znaky příkazem \mathcode
. V klasickém TeXu
jsou deklarovány jen použité řídicí sekvence \sum
, \pi
,
\infty
pomocí \mathchardef
, jak je možné se přesvědčit
například v Knuthově souboru plain.tex
.
I formát CSplain je možné vygenerovat s XeTeXem nebo LuaTeXem. CSplain ale z historických důvodů má implicitně vnitřní kódování il2 (viz níže). Ovšem je snadné přepnout na jiné kódování (T1 nebo Unicode). Začátek dokumentu v CSplainu pod 16bitovým TeXem může tedy vypadat třeba takto:
\input ucode % redefinice maker (závislých na kódování) podle Unicode \chyph % vzory dělení češtiny (nyní budou v Unicode) \input lmfonts % načtení Latin Modern fontů v Unicode Ahoj světe! Jak se mají žlutí koňové? \end
Možnost použít unicodové fonty je poměrně nová. Ještě nedávno TeX uměl pracovat pouze s metrickými údaji fontů s maximálně 256 znaky. Vrátíme se tedy na počátek 90. let a popíšeme, jak vznikala podpora češtiny a slovenštiny. Kvůli častému konzervativnímu přístupu TeXistů se některé tyto věci používají dodnes.
Zhruba v roce 1991 jsme navrhli mírnou modifikaci Computer Modern fontů, tzv. CSfonty. Ty přidávají kompletní akcentované znaky české a slovenské abecedy do druhé poloviny tabulky podle ISO-8859-2. Toto kódování se nazývá il2. Vzory dělení češtiny i slovenštiny jsou do CSplainu načteny v il2 a CSfonty na to navazují. V té době se pro češtinu používalo několik jednobytových kódování vstupních souborů: ISO-8859-2, CP1250, CP852, KOI8-CS, Kamenických atd. Mezi různými prostředími dle použitého kódování a interním kódováním il2 bylo potřeba správně konfigurovat input procesor TeXu, který pro případ překódování tam i zpět na úrovni „byte to byte“ byl připraven již Knuthem. Docela podrobně jsem tuto problematiku popsal v článku Putování písmene ř z klávesy na papír (1997).
Na začátku 90. let na konferenci v Corku se TeXisté dohodli a vymezili evropské kódování fontů. Využili všech tehdy dostupných 256 pozic. První polovina tabulky respektovala viditelné ASCII znaky, druhá ISO-8859-1 a do volných míst byly nacpány ostatní znaky latinkou píšících evropanů, tedy i naše abeceda. Kódování nazvali T1 alias Cork. Jádro LaTeXu bylo Jiřím Zlatuškou upraveno tak, aby dokázalo načíst vzory dělení v obou kódováních (il2 i T1) a tím vznikl CSLaTeX schopný pracovat jak s CSfonty tak s T1 kódovanými fonty. Kresby znaků české abecedy byly v CSfontech vydařenější než v analogickém fontu kódovaném podle T1 a tím se asi vysvětluje, proč CSLaTeX přežíval dvě desetiletí. Já jsem navíc v il2 kódování připravil počeštění základních PostSriptových fontů.
Fonty kódované podle T1 byly většinou z různých zdrojů (třeba i bez
akcentovaných znaků) generovány za použití nástroje fontinst
, který
vytváří virtuální kompozitní znaky, jež může pak přímo používat TeX. Bohužel
v tomto nástroji byla a je chyba v
konfiguraci znaku ď a ť, takže desítky, možná stovky, takto vytvořených fontů
přítomných v TeXové distribuci jsou pro češtinu nepoužitelné. Když jsem to
teprve loni objevil (protože vesměs používám il2 kódované fonty), docela jsem se
podivil, že toto žádný uživatel za těch 20 let nereportoval. Že by všichni čeští
TeXisté užívali výhradně il2?
Kuriózní na T1 kódování je například to, že sice bylo navrženo pro Evropu, ale
stalo se tak v roce 1990, kdy ještě nikdo netušil, že bude existovat znak Euro.
V T1 tabulce najdeme libru, dolar, ale Euro nikoli. Nicméně TeX umožňuje na
úrovni maker snadno připojit ke každému 256znakovému fontu libovolné množství
expertních sad tak, že uživatel ani nepozná, že TeX uvnitř přepíná mezi základním
řezem a k němu připojenou expertní sadou. Viz například soubor maker
exchars.tex
. V expertní sadě
samozřejmě Euro přítomno je.
Nové fonty například z projektu TeXGyre jsou primárně připraveny v OpenType, ale jsou k nim rovněž vygenerovány klasické metriky pro TeX podle rozličných kódování, která se během osmibitového období narodila a začala v TeXových distribucích přežívat.
V roce 2000 narůstal požadavek používat UTF-8 kódování vstupních souborů.
V té době byla ještě možnost číst unicodové fonty v nedohlednu, formát
OpenType (2005) neexistoval. Konverze UTF-8 na 8 bitů uvnitř TeXu byla v LaTeXu
řešena na úrovni maker: \usepackage[utf8]{inputenc}
. Ovšem takto řešená
konverze přináší na nízké úrovni programování maker docela problémy. Proto jsem
počátkem milénia rozšířil input procesor TeXu tak, aby dokázal kromě „byte to byte“
konverze provádět i konverzi více bytů na jeden byte nebo na řídicí sekvenci.
Počet UTF-8 znaků je sice značný, ale počet řídicích sekvencí, na které se to
automaticky může uvnitř TeXu konvertovat, je víceméně neomezený. Každá řídicí
sekvence může navazovat na své makro, které vyšťourá znak buď z aktuální
základní sady nebo z některé z expertních sad přidružených aktuálnímu
fontu. Toto řešení jsem nazval encTeX.
Současný CSplain nad pdfTeXem s UTF-8 kódovaným vstupem využívá encTeX.
Implicitně rozumí znakům české a slovenské abecedy a textovým
znakům, na které měl Knuth řídicí sekvenci (typu \ae
). Po načtení
dalších maker rozumí znakům z dalších částí Unicode tabulky. Například po
\input utf8math
je CSplain schopen interpretovat matematické vzorečky
s UTF-8 znaky, jak bylo ukázáno v příkladu v úvodu tohoto článku.
verze | rok | poznámka |
TeX v.<3 | < 1990 | ASCII a řídicí sekvence, interně 7 bitů |
TeX v. 3.* | ≥ 1990 | interně 8 bitů a řídicí sekvence, kódování il2, T1, konverze byte to byte |
encTeX | ∼ 2002 | UTF-8 → 8 bitů+řídicí sekvence, kódování il2, T1 |
XeTeX | ∼ 2006 | umí číst OpenType fonty, UTF-8 na vstupu, interně Unicode |
LuaTeX | ∼ 2010 | umí číst OpenType fonty, UTF-8 na vstupu, interně Unicode |
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.