Položte na stůl stránku japonského románu a první věc, které si všimnete, je, že text běží dolů ve sloupci, nikoli napříč řádkem, a že sloupce postupují od pravého okraje listu směrem doleva. Čtenáři, který na tom vyrostl, přijde horizontální text tak trochu neosobní (klinický). Inženýrský problém spočívá v tom, že formát PDF, stejně jako téměř každý digitální textový systém, byl postaven na horizontální účaří (baseline), která roste zleva doprava, a záznam obsahu (content stream) nemá žádný koncept pro instrukci typu „tento odstavec místo toho napiš dolů“. Takže když aplikace v Delphi musí vyprodukovat certifikát, báseň, kousek značení nebo tradičně formátovaný právní dokument pro tchajwanského, japonského nebo korejského čtenáře, musí se rozvržení poskládat ručně: jeden znak pod druhý, jeden sloupec nalevo od předchozího
HotPDF vám nabízí přepínač (switch), který účetnictví o každém znaku obstará za vás. Font, který nastavíte, s sebou nese příznak (flag) IsVertical a jakmile je zapnutý, jediné volání TextOut poskládá celý řetězec do svislého sloupce místo toho, aby ho vedlo po horizontální účaří (baseline). Umístění sloupců, pořadí zprava doleva a jedno tiše důležité nahrazení znaku – to je přesně to, čím se zabývá zbytek této stránky

Přepínač žije v SetFont
Vertikální rozložení není vlastností stránky ani celého dokumentu. Je to vlastnost písma (fontu), kterým kreslíte, a zapínáte ji pátým argumentem metody SetFont:
// SetFont(FontName, FontStyle, Size, FontCharset, IsVertical)
// The 5th argument flips the current font into vertical mode.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, DEFAULT_CHARSET, False); // horizontal
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, DEFAULT_CHARSET, True); // vertical
Protože příznak jede s písmem, přepínáte mezi vodorovným a svislým způsobem psaní jednoduše tím, že znovu zavoláte SetFont s jiným posledním argumentem. Stránka může mít napříč horní částí vodorovný nadpis a pod ním svislý hlavní text. HotPDF udržuje tyto dva režimy oddělené podle objektu fontu (per font object) spíše než podle stránky (per page). Právě to umožňuje smíšená rozložení bez nutnosti jakéhokoliv speciálního ošetřování režimů z vaší strany: každý TextOut po vertikálním volání SetFont se vrství shora dolů (stacks), každý TextOut po tom horizontálním běží podél účaří a poslední volání SetFont má vždy přednost (vyhrává)
Čtvrtým argumentem je znaková sada (character set) Windows, což je ten samý parametr, jaký přebírá horizontální volání. Předání DEFAULT_CHARSET ponechává systému vyřešení glyphů řetězec po řetězci, což je zde důležité, protože vertikální dokument často míchá různá písma (scripts). Vše ostatní týkající se fontu stále platí: musí být nainstalován na počítači, na kterém probíhá kompilace, a téměř vždy budete chtít použít FontEmbedding := True, aby soubor na počítači čtenáře (který písmo Arial Unicode MS možná nikdy neměl) vykreslil úplně stejné glyphy CJK (čínština, japonština, korejština)
Jedno volání TextOut je jeden sloupec
Se zapnutým vertikálním fontem volání TextOut již neroztahuje svůj řetězec z daného bodu do šířky. Posadí první znak na vršek a se zbytkem schází přímo dolů, postupujíc u každého piktogramu (glyph) o výšku řádku fontu. Souřadnice X, kterou předáte, zafixuje polohu sloupce; souřadnice Y, kterou předáte, určuje, kde nahoře sloupec začíná. Abyste rozvrhli skutečnou pasáž textu, vydáte tedy jedno volání TextOut pro každý sloupec a s každým voláním postoupíte v ose X směrem doleva, protože sloupce CJK se čtou zprava doleva
var
Pdf: THotPDF;
const
ColTop = 760; // y of the first glyph in every column (points)
ColGap = 28; // horizontal distance between columns
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'VerticalText.pdf';
Pdf.FontEmbedding := True; // embed the CJK face for portable rendering
Pdf.BeginDoc;
Pdf.CurrentPage.Size := psA4;
// A horizontal heading first, in the ordinary writing mode.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 16, DEFAULT_CHARSET, False);
Pdf.CurrentPage.TextOut(60, 800, 0, 'Tang poem, vertical layout');
// Switch the font into vertical mode; every TextOut below now stacks.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 18, DEFAULT_CHARSET, True);
// Columns advance right to left, so X decreases with each call.
Pdf.CurrentPage.TextOut(520, ColTop, 0, '床前明月光');
Pdf.CurrentPage.TextOut(520 - ColGap, ColTop, 0, '疑是地上霜');
Pdf.CurrentPage.TextOut(520 - ColGap * 2, ColTop, 0, '舉頭望明月');
Pdf.CurrentPage.TextOut(520 - ColGap * 3, ColTop, 0, '低頭思故鄉');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Báseň se pak čte tak, jak se sluší a patří: nejprve sloupec nejvíce vpravo, shora dolů, a pak oko přeskočí doleva na další sloupec. V samotném řetězci (string) nic z toho pořadí kódováno není. Kódujete ho do souřadnic X tak, že je s každým dalším voláním zmenšujete. Zmýlíte-li se a uděláte směr obráceně, verš nakonec vyjde naopak, což je vlastně ta jediná a nejčastější chyba, které se lidé dopouštějí, když předělávají horizontální rozvržení (layout) na vertikální
Souřadnice: dolů po stránce, zprava doleva
Ve hře jsou dvě osy, které táhnou opačnými směry, takže se vyplatí být precizní. HotPDF měří vše od levého dolního rohu stránky (bottom-left corner) přičemž osa Y roste směrem vzhůru a udává se v tiskových bodech (points). Vertikální sloupec proto začíná na vysokém čísle Y (těsně u vršku stránky) a znaky odtamtud sestupují směrem dolů, jak z něj knihovna HotPDF odčítá výšku řádku pro každý z nich. Počáteční Y nastavíte u každého sloupce jenom jednou a daná komponenta (HotPDF) následný sestup zvládne sama
Horizontální osa je tou, kterou řídíte manuálně vy sami. Každý sloupec sedí na své vlastní souřadnici X, po sobě jdoucí sloupce kráčejí do vždy menších hodnot pro X (skutečné souřadnice doleva), poněvadž pořadí samotného čtení obvykle probíhá přesně zprava doleva (right to left). Praktickým rytmem pro tuto akci (sensible rhythm) bývá prvotní zvolení X podle nejpravějšího možného sloupce, z kterého u každého následujícího z volání následně rovnou fixní mezeru pro sloupec odečtete přesně tak, jak ukazuje náš příklad použitím konstanty ColGap. Jaká ta mezera bude je ale již pouze na vás. Příliš těsná totiž způsobí to, že sousedící (adjacent columns) sloupce se začnou dotýkat a přílišná volnost blok opticky vyprázdní. Děláte-li (For body text) hlavní řádky (12 do 18 bodů), pak mezera těsně (a little larger) převyšující přímo velikost textu, se vizuálně čte celkově úplně (comfortably) s největší přirozeností
Znaky (glyphy), které musí změnit tvar
Několik znaků není pouhými otočenými kopiemi svých horizontálních verzí; při vertikálním textu musí být nahrazeny. Tím, který za vás HotPDF vyřeší, je japonská značka pro prodloužení zvuku ー (U+30FC) – čárka pro dlouhou samohlásku, která se objevuje ve slovech z katakany, jako je コーヒー. Při horizontálním psaní jde o krátkou pomlčku na účaří. Pokud byste tento stejný glyph vložili do sloupce, ležel by naplocho přes sloupec, což je špatně: ve vertikální japonštině se tato značka mění na svislou čáru spojující dva znaky, mezi kterými se nachází. HotPDF detekuje znak U+30FC ve vertikální cestě a vykreslí jej jako svislou čáru (U+007C), takže značka dlouhé samohlásky směřuje správně bez jakékoliv práce z vaší strany
Toto jediné nahrazení pokrývá případ, který rozbíjí většinu naivních implementací. Je však dobré vědět, kam tento obecný problém sahá hlouběji. Plnohodnotná vertikální typografie také rotuje latinská písmena a západní interpunkci o devadesát stupňů, posouvá malou kanu a přemisťuje závorky a čárky do jejich vertikálních podob. Kompletní implementace tohoto chování se nachází ve vertikálních funkcích formátu OpenType samotného fontu, nikoli v pevných pravidlech programu. HotPDF dokáže tyto funkce využít, pokud je font obsahuje: vertikální alternativy (funkce GSUB vert a vrt2) a vertikální kerning (vyhledávání GPOS vkrn a vpal) jsou volitelné (opt-in) a uplatňují se ve vertikální cestě pouze tehdy, když je aktivní font skutečně definuje. Pro smíšený CJK text v jednom fontu se širokým pokrytím (např. Arial Unicode MS) stačí vestavěné ošetření U+30FC a rovnoměrný krok výšky řádku k vytvoření správných a čitelných sloupců. Funkce OpenType začnou být důležité ve chvíli, kdy přejdete k fontu navrženému pro jemnou vertikální sazbu a chcete využít jeho nativní pozicování kany a mezery mezi glyphy
Míchání písem a orientací na jedné straně
Skutečné dokumenty jsou málokdy čistě jednolité. Vertikální japonská stránka může obsahovat horizontální anglický popisek, číslo stránky dole nebo blok korejštiny sázený vertikálně vedle japonštiny. Protože je vertikální příznak přepínačem na úrovni fontu, skládáte tyto prvky střídáním volání SetFont namísto správy nějakého celostránkového stavu. Nastavte horizontální font, zapište průběžné záhlaví (running header) a číslo stránky, nastavte vertikální font, rozložte sloupce, a znovu nastavte horizontální font pro zápatí. Každá oblast přebírá režim z posledního volání SetFont, takže jedinou potřebnou disciplínou je zavolat jej, kdykoli změníte směr
Při míchání písem je třeba naplánovat ještě jeden detail: čínské, japonské a korejské ideogramy jsou téměř čtvercové a skládají se s rovnoměrným krokem, ale latinka vložená do vertikálního sloupce tento jednotný posun nemá. Pokud potřebujete do jinak vertikálního textu vložit pár latinských slov, promyšleně se rozhodněte, zda by měla být otočena a běžet dolů sloupcem, nebo zda je necháte vzpřímená jako krátkou horizontální vložku. Tento fragment pak umístěte vlastním voláním TextOut namísto toho, abyste ho nechali "svézt se" na vertikálním kroku určeném pro ideogramy. Pokud k této smíšené části přistoupíte jako k samostatnému problému umístění, udržíte tím rytmus sloupce neporušený
Od ukázky k produkčnímu nasazení
Dílky jsou to malé a skládají se předvídatelně. Zapněte vertikální příznak v SetFont, vydávejte jedno volání TextOut na sloupec z pevné horní souřadnice Y a při každém dalším volání zmenšujte X, aby se sloupce četly zprava doleva. Zahrňte do PDF samotný font (embed), aby glyphy CJK přežily cestu k počítači čtenáře, a nechte komponentu, ať se postará o značku dlouhé samohlásky U+30FC a – pokud to font podporuje – i o vertikální funkce OpenType. Odtud je nasazení rozvržení do produkce už většinou jen aritmetika: odvození pozic X sloupců ze změřené šířky bloku, rozdělování dlouhých pasáží do sloupců tak, aby se vešly na výšku stránky, a vyhrazení místa pro horizontální záhlaví a čísla stránek (folios)
Širší souvislosti s textem a fonty, na kterých toto vše staví (včetně konvencí horizontálního volání TextOut a registrace Unicode fontů), najdete ve vícejazyčném příkladu Hello World a v ukázce k použití TextOut. Vertikální přepínač v SetFont a volání TextOut, která jsou zde uvedena, tvoří součást komponenty HotPDF pro Delphi a C++Builder