Technický článek

Vertikální japonský a čínský text v PDF s Delphi

PDF Library for Delphi kreslí japonský a čínský text dolů po stránce. SetVerticalWritingMode vertikální zápis zapne, běžná volání DrawText pak běží směrem dolů a GetVerticalWritingMode hlásí aktuální stav. Dříve, než to existovalo, znamenalo vertikální sázení textu umístit každý znak ručně a doufat, že rozestupy budou vypadat správně

Vertikální zápis není horizontální text otočený o devadesát stupňů. Znaky zůstávají vzpřímené, posun běží dolů místo napříč a řada znaků se úplně mění tvar — což je ta část, která odlišuje dokument čitelný přirozeně od dokumentu, jejž japonský čtenář na první pohled pozná jako strojově vyrobený

Diagram PDF Library for Delphi srovnávající otočenou vodorovnou linku textu se skutečným svislým režimem psaní, kde glyfy zůstávají vzpřímené a posun běží po straně dolů
Svislý zápis staví znaky vzpřímeně s vertikálními metrikami daného řezu místo otáčení vodorovné řádky a zkopírovaný sloupec se čte zpětně znak za znakem

Co se mění uvnitř PDF

Text nakreslený tímto způsobem prochází Type0 písmem ve vertikálním režimu zápisu nesoucím vlastní vertikální metriky písma. To hraje roli ve dvou směrech. Čtečka posouvá každý znak o vzdálenost, kterou zamýšlel jeho návrhář, nikoli o jednotný krok, takže sloupce má rytmus, pro který byl typ písma nakreslen. A kopírování textu ven vrátí původní znaky, protože vertikální běh je stále skutečný text se správným mapováním, nikoli sled umístěných glyfů

Písmo, které nenese vlastní vertikální metriky, posouvá o jeden em na znak, což je přesně to, co by čtečka udělala s výchozím nastavením. O tento fallback stojí za to vědět, protože je to rozdíl, který uvidíte, když se dokument vykreslí správně s řádným CJK písmem a vypadá mechanicky sázené s latinkovým písmem, které náhodou obsahuje pár kana

var
  Lib: TPDFlib;
  H: Double;
begin
  Lib := TPDFlib.Create;
  try
    Lib.SetOrigin(1);
    Lib.AddTrueTypeFont('MS Mincho', 1);      // 1 = vložit řez
    Lib.SetTextSize(12);
    Lib.SetVerticalWritingMode(1);            // běžné DrawText teď běží dolů
    H := Lib.GetVerticalTextHeight('MS Mincho', 12, '第三章 保守点検');
    Lib.DrawText(480, 72, '第三章 保守点検');
    Lib.SetVerticalWritingMode(0);            // zpět na horizontální
    Lib.DrawText(72, 72 + H, 'Chapter 3');
    Lib.SaveToFile('manual-ja.pdf');
  finally
    Lib.Free;
  end;
end;

Proč vypadají závorky ve vertikálním textu špatně?

Protože závorka má dvě formy a ve sloupci patří jen jedna. Závorky, značka dlouhé samohlásky a malé kana se kreslí odlišně, když text běží dolů po stránce — kulatá závorka se otočí, aby ležela podél sloupce místo napříč, a značka dlouhé samohlásky se změní na vertikální tah. Nakreslete horizontální formy do vertikálního sloupce a každá z nich bude ležet na boku

PDF Library for Delphi bere formy z vlastní vertikální funkce písma, takže každý rez dodává to, co nakreslil jeho návrhář, nikoli substituci uhádnutou ze znaku. Tento rozdíl má vliv na správnost: tabulka uhádnutých substitucí je správná u běžných případů a špatná u písem, která se znakem zacházejí jinak, a písmo, které nejmenuje žádné vertikální formy, se kreslí přesně jako dříve, místo aby bylo vmanipulováno do tabulky, o kterou nežádalo

GetVerticalTextHeight měří formy, které budou skutečně nakresleny, takže sloupec, jehož znaky mění tvar, je správně změřen. Měřit horizontální formy a kreslit vertikální je klasickým zdrojem sloupců, které o pár znaků přetéčou svůj rámeček

Diagram PDF Library for Delphi ukazující, jak vertikální vlastnost fontu dodává formy závorek a znaku prodloužené hlásky ležící podél svislého sloupce, zatímco obyčejné znaky stojí nezměněny, vše měřeno přes GetVerticalTextHeight
Vlastní vertikální feature řezu rozhoduje, které glyfy ve sloupci změní tvar, a GetVerticalTextHeight měří tvary, které se skutečně nakreslí

Kreslení jednoho běhu beze změny režimu

DrawVerticalText nakreslí jeden běh vertikálně, přijímá pozici, název písma, velikost a text a režim zápisu nechává na pokoji. Použijte ho pro vertikální výjimku uvnitř horizontálního dokumentu — hřbet štítku, razítko, jediný sloupec jmen — kde zapínání a vypínání globálního režimu kolem každé volby představuje víc stavu, než si úloha zaslouží

Horizontální a vertikální formy jednoho písma se interně drží odděleně, takže stránka může nést oboje, aniž by se jedno do druhého zamíchalo. Právě to dělá smíšenou stránku praktickou: japonská knižní stránka s vertikálním tělem textu a horizontálními běžícími záhlavími, nebo čínský certifikát s vertikálním titulkem nad horizontálními řádky detailů

// Jeden vertikální běh uvnitř jinak horizontální stránky
Lib.DrawVerticalText(520, 96, 'MS Mincho', 14, '保守点検記録');
// Horizontální text kolem něj není ovlivněn
Lib.DrawText(72, 96, 'Maintenance inspection record');

Správné nastavení písma před čímkoli jiným

Vertikální zápis závisí úplně na písmu. CJK písmo s řádnými vertikálními metrikami a vertikální funkcí produkuje správný výstup bez další práce; písmo bez nich produkuje vzpřímené znaky posunující se o em na znak a žádnou změnu tvaru. Pokud vertikální text vypadá jemně špatně, prozkoumejte písmo dříve než kód

Vkládání písma se řídí obvyklými pravidly a obvyklými náklady. Plné CJK písmo je objemné, takže subsetting není pro dokumenty, které se někam posílají, volitelný — poznámky k optimalizaci velikosti PDF a subsettingu písem popisují, co čekat, a průvodce vkládáním chybějících písem do existujícího PDF řeší případ opravy, kdy vertikální dokument přijde bez svých písem

Kde stále vertikální text potřebuje rozhodnutí o layoutu od vás

Pořadí sloupců. Japonský vertikální text běží po sloupcích zprava doleva, takže dvousloupková stránka začíná u pravého okraje a žádné nastavení režimu zápisu to z textu nevyvodí. Stejné platí o pořadí stránek v dokumentu, který se jako celek čte zprava doleva, a o tom, kde sedí furigana, poznámky pod čarou a popisky obrázků

Diagram PDF Library for Delphi: DrawVerticalText umístí jeden vzpřímený svislý běh vedle obyčejných vodorovných řádků DrawText na sdílené straně, aniž by se dotkl globálního režimu psaní
DrawVerticalText nese vlastní písmo, velikost i pozici, takže jediný svislý sloupec koexistuje s vodorovnými voláními kolem sebe

Co knihovna garantuje, je, že každý běh je poskládán správně: správné formy, správné posuny, extrahovatelný text. To, kam běhy na stránce umístit, je problém layoutu, a u dokumentů sestavovaných z dat je průvodce vyhledáváním textu a enumerací elementů stránky užitečný k ověření, že to, co skončilo na stránce, je to, co jste zamýšleli

PDF Library for Delphi je nativní Pascal PDF knihovna pro Delphi, C++Builder a Lazarus a vertikální CJK zápis je součástí kreslícího API, nikoli doplňkem — viz stránka produktu PDF Library for Delphi pro přehled funkcí textu a písem