Når du setter en japansk roman på siden, er det første du legger merke til at teksten går nedover spalten, ikke på tvers av linjen, og at spaltene fortsetter fra høyre kant av arket mot venstre. En leser som har vokst opp med dette, synes horisontal tekst virker svakt klinisk. Det tekniske problemet er at PDF, i likhet med nesten alle digitale tekstsystemer, er bygd rundt en horisontal grunnlinje som vokser fra venstre til høyre, og en innholdsstrøm (content stream) har ingen oppfatning av "skriv dette avsnittet nedover i stedet." Så når en Delphi-applikasjon må produsere et sertifikat, et dikt, et skilt, eller et juridisk dokument i tradisjonelt format for en taiwansk, japansk eller koreansk leser, må oppsettet settes sammen for hånd: ett tegn under det neste, én kolonne til venstre for den forrige
HotPDF gir deg en bryter som gjør den tegn-for-tegn-bokføringen for deg. Skriften du angir har et IsVertical-flagg, og når det er på, stabler et enkelt TextOut-kall en hel streng inn i en vertikal kolonne i stedet for å kjøre den langs en grunnlinje. Kolonneplasseringen, høyre-til-venstre-rekkefølgen, og en stille viktig glyff-substitusjon er det resten av denne siden går gjennom

Bryteren bor på SetFont
Vertikalt oppsett er ikke en egenskap ved siden eller dokumentet. Det er en egenskap ved fonten du tegner med, og du slår den på med det femte argumentet til SetFont:
// SetFont(FontName, FontStyle, Size, FontCharset, IsVertical)
// Det femte argumentet bytter den gjeldende skrifttypen til vertikal modus.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, DEFAULT_CHARSET, False); // horisontal
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, DEFAULT_CHARSET, True); // vertikal
Siden flagget følger fonten, bytter du mellom horisontal og vertikal skriving ganske enkelt ved å kalle SetFont igjen med et annet siste argument. En side kan ha en horisontal tittel øverst og vertikal brødtekst under den, og HotPDF holder de to modusene adskilt per font-objekt snarere enn per side. Det er dette som gjør blandede oppsett mulig uten noen spesiell modushåndtering på din side: hvert TextOut etter en vertikal SetFont stables, hvert TextOut etter en horisontal løper langs grunnlinjen, og den siste SetFont vinner
Det fjerde argumentet er Windows-tegnsettet, det samme som et horisontalt kall tar. Ved å sende DEFAULT_CHARSET lar systemet løse glyffer per streng, noe som er viktig her fordi et vertikalt dokument ofte blander skript. Alt annet ved skrifttypen gjelder fortsatt: den må være installert på bygge-maskinen, og du ønsker nesten alltid FontEmbedding := True slik at filen gjengir de samme CJK-glyffene på en leser som aldri hadde Arial Unicode MS
Ett TextOut-kall er én kolonne
Med en vertikal skrifttype aktiv sprer ikke lenger et TextOut-kall strengen sin sidelengs fra det gitte punktet. Den planter det første tegnet øverst og går resten rett ned, og går frem med fontens linjehøyde for hver glyff. X-en du passerer, fikserer kolonnen; Y-en du passerer, fikserer hvor toppen av kolonnen begynner. For å legge ut et ekte avsnitt utsteder du derfor én TextOut per kolonne og trer X til venstre mellom kall, fordi CJK-kolonner leses fra høyre til venstre
var
Pdf: THotPDF;
const
ColTop = 760; // y for det første tegnet i hver kolonne (punkter)
ColGap = 28; // horisontal avstand mellom kolonner
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'VerticalText.pdf';
Pdf.FontEmbedding := True; // bygg inn CJK-skrifttypen for portabel gjengivelse
Pdf.BeginDoc;
Pdf.CurrentPage.Size := psA4;
// En horisontal overskrift først, i ordinær skrivemodus.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 16, DEFAULT_CHARSET, False);
Pdf.CurrentPage.TextOut(60, 800, 0, 'Tang-dikt, vertikalt oppsett');
// Bytt fonten til vertikal modus; hvert TextOut nedenfor stables nå.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 18, DEFAULT_CHARSET, True);
// Kolonner går frem fra høyre til venstre, så X minker for hvert kall.
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;
Diktet leses som det skal: den høyreste kolonnen først, fra topp til bunn, deretter hopper øyet til venstre til neste kolonne. Ingenting ved strengen i seg selv koder for den rekkefølgen. Du koder den i X-koordinatene, og reduserer dem kall for kall. Tar du feil retning kommer verset ut i revers, som er den desidert vanligste feilen når man overfører et horisontalt oppsett til et vertikalt
Koordinater: nedover siden, fra høyre til venstre
To akser er i spill og de trekker i motsatte retninger, så det er verdt å være nøyaktig. HotPDF måler fra nederste venstre hjørne av siden, med Y økende oppover, i punkter. En vertikal kolonne starter derfor med en høy Y (nær toppen av arket), og tegnene går ned derfra ettersom HotPDF trekker fra en linjehøyde for hver enkelt. Du angir den start-Y-en én gang per kolonne, og komponenten håndterer nedstigningen
Den horisontale aksen er den du styrer manuelt. Hver kolonne sitter ved sin egen X, og påfølgende kolonner trer til mindre X-verdier fordi leserekkefølgen er fra høyre til venstre. En fornuftig rytme er å velge X-en til høyreste kolonne, deretter trekke fra et fast kolonnemellomrom for hvert påfølgende kall, slik eksempelet gjør med ColGap. Avstanden er opp til deg å velge; for tett, og nabokolonner berører hverandre, for løst og blokken ser glissen ut. For brødtekst på 12 til 18 punkter, leses et gap litt større enn fontstørrelsen komfortabelt
Glyffer som må endre form
Noen få tegn er ikke bare roterte kopier av sine horisontale selv; de må erstattes når teksten blir vertikal. Det ene HotPDF håndterer for deg er det japanske forlenget-lyd-merket ー (U+30FC), den lange vokal-streken som dukker opp i katakana-ord som コーヒー. Tegnet horisontalt er det en kort strek på grunnlinjen. Hvis du stablet den samme glyffen inn i en kolonne, ville den ligge flatt over kolonnen, noe som er feil: i vertikal japansk blir merket et vertikalt strøk som forbinder de to tegnene den sitter mellom. HotPDF oppdager U+30FC i den vertikale stien og tegner det som en vertikal stolpe (U+007C) slik at lang-vokal-merket peker rett vei uten noe arbeid fra deg
Den ene substitusjonen dekker tilfellet som knekker de fleste naive implementasjoner, men det er verdt å vite hvor det generelle problemet går dypere. Full vertikal typografi roterer også latinske bokstaver og vestlig tegnsetting nitti grader, forskyver små kana og flytter hakeparenteser og kommaer til deres vertikale former, og en fullstendig implementering av det bor i en fonts OpenType vertikale funksjoner i stedet for faste regler. HotPDF kan benytte disse funksjonene når skrifttypen bærer dem: vertikale alternativer (vert og vrt2 GSUB-funksjonene) og vertikal kerning (vkrn og vpal GPOS-oppslag) er valgfrie, og brukes bare langs den vertikale banen når den aktive fonten faktisk definerer dem. For blandet CJK-tekst i en enkelt bred-dekning-skrifttype som Arial Unicode MS, er den innebygde U+30FC-håndteringen pluss et jevnt linjehøydetrinn nok til å produsere korrekte, lesbare kolonner; OpenType-funksjonene betyr noe når du flytter til en skrifttype designet for fin vertikal setting og vil ha dens opprinnelige kana-posisjonering og avstand mellom glyffer
Blande skript og orienteringer på én side
Ekte dokumenter er sjelden rene. En vertikal japansk side kan ha en horisontal engelsk bildetekst, et sidetall langs bunnen, eller en blokk med koreansk satt vertikalt ved siden av den japanske. Fordi det vertikale flagget er en bryter på skrifttypenivå, komponerer du disse ved å veksle SetFont-kall snarere enn ved å administrere noen sidetilstand. Sett en horisontal skrifttype, skriv den løpende overskriften og sidetallet, sett en vertikal font, legg kolonnene, sett en horisontal skrifttype igjen for bunnteksten. Hvert område plukker opp modusen til den sist brukte SetFont, så den eneste disiplinen som kreves er å kalle den hver gang du skifter retning
Én detalj å planlegge for når skript blandes: Kinesiske, japanske og koreanske ideogrammer er nær kvadratiske og stables med et jevnt trinn, men latinske løp innebygd i en vertikal kolonne har ikke denne jevne fremgangen. Hvis du trenger et par latinske ord i en ellers vertikal tekst, må du bevisst bestemme om de skal roteres til å løpe nedover spalten eller settes stående som en kort horisontal innfelling, og posisjonere dette fragmentet med sitt eget TextOut istedenfor å la det ri den vertikale trinningen ment for ideogrammer. Å behandle den blandede teksten som et eget plasseringsproblem holder kolonnekrytmen intakt
Fra eksempel til produksjon
Brikkene er små, og de settes sammen på forutsigbart vis. Slå på det vertikale flagget i SetFont, utsted ett TextOut per kolonne fra en fast Y på toppen, og senk X på tvers av kall slik at kolonnene leses fra høyre til venstre. Bygg inn skrifttypen slik at CJK-tegnene overlever reisen til leserens maskin, og la komponenten ta seg av U+30FC lang-vokal-merket og, der skrifttypen støtter det, de vertikale OpenType-funksjonene. Derfra er produksjonering av oppsettet for det meste aritmetikk: å utlede kolonne-X-posisjoner fra en målt blokkbredde, å bryte opp lange avsnitt i kolonner som passer til sidehøyden, og reservere plass for horisontale topp- og bunntekster
For den bredere overflaten av tekst og skrifttyper dette bygger på, inkludert horisontale TextOut-konvensjoner og Unicode font-registrering, se Hello World-eksempelet på flere språk og TextOut-eksempelet. SetFonts vertikale bryter og TextOut-kallene vist her er en del av HotPDF-komponenten for Delphi og C++Builder