Sæt en japansk roman på siden, og det første, du bemærker, er, at teksten løber ned ad kolonnen, ikke på tværs af linjen, og at kolonnerne rykker frem fra højre kant af arket mod venstre. En læser, der er opvokset med det, synes, at vandret tekst er svagt klinisk. Det tekniske problem er, at PDF, ligesom næsten ethvert digitalt tekstsystem, blev bygget op omkring en vandret grundlinje, der vokser fra venstre mod højre, og en indholdsstrøm har ingen forestilling om at "skrive dette afsnit nedad i stedet". Så når et Delphi-program skal producere et certifikat, et digt, et stykke skiltning eller et juridisk dokument i traditionelt format til en taiwanesisk, japansk eller koreansk læser, skal layoutet samles manuelt: ét tegn under det næste, én kolonne til venstre for den sidste
HotPDF giver dig en kontakt, der foretager bogføringen pr. tegn for dig. Den skrifttype, du indstiller, bærer et IsVertical-flag, og når det er slået til, stabler et enkelt TextOut-kald en hel streng til en lodret kolonne i stedet for at køre den langs en grundlinje. Kolonneplaceringen, rækkefølgen fra højre mod venstre og én stille vigtig glyph-erstatning er det, som resten af denne side arbejder igennem

Kontakten lever på SetFont
Lodret layout er ikke en egenskab ved siden eller dokumentet. Det er en egenskab ved den skrifttype, du tegner med, og du aktiverer den med det femte argument til 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
Fordi flaget rider på skrifttypen, skifter du mellem vandret og lodret skrivning blot ved at kalde SetFont igen med et andet sidste argument. En side kan indeholde en vandret titel hen over toppen og lodret brødtekst under den, og HotPDF holder de to tilstande adskilt pr. skrifttypeobjekt i stedet for pr. side. Det er det, der gør blandede layout mulige uden nogen speciel tilstandshåndtering fra din side: hvert TextOut efter et lodret SetFont stables, hvert TextOut efter et vandret kører langs grundlinjen, og det sidste SetFont vinder
Det fjerde argument er Windows-tegnsættet, det samme som et vandret kald tager. Ved at videregive DEFAULT_CHARSET lader du systemet løse glyffer pr. streng, hvilket betyder noget her, fordi et lodret dokument ofte blander scripts. Alt andet om skrifttypen gælder stadig: den skal være installeret på bygge-maskinen, og du vil næsten altid have FontEmbedding := True, så filen gengiver de samme CJK-glyffer på en læser, der aldrig har haft Arial Unicode MS
Ét TextOut-kald er én kolonne
Med en lodret skrifttype aktiv spreder et TextOut-kald ikke længere sin streng sidelæns fra det givne punkt. Det planter det første tegn øverst og går resten lige ned og rykker frem med skrifttypens linjehøjde for hver glyph. Det X, du videresender, fastlægger kolonnen; det Y, du videresender, fastlægger, hvor toppen af kolonnen begynder. For at layoute en rigtig passage udsender du derfor ét TextOut pr. kolonne og træder X mod venstre mellem kaldene, fordi CJK-kolonner læses fra højre mod venstre
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;
Digtet læses, som det skal: kolonnen yderst til højre først, fra top til bund, hvorefter øjet hopper til venstre til næste kolonne. Intet ved selve strengen koder denne rækkefølge. Du koder den i X-koordinaterne og mindsker dem kald for kald. Få retningen baglæns, og verset kommer ud omvendt, hvilket er den absolut mest almindelige fejl, når man overfører et vandret layout til lodret
Koordinater: ned ad siden, højre mod venstre
To akser er i spil, og de trækker i hver sin retning, så det er værd at være præcis. HotPDF måler fra nederste venstre hjørne af siden, med Y stigende opad, i punkter. En lodret kolonne starter derfor ved et højt Y (nær toppen af arket), og tegnene falder derfra, da HotPDF trækker en linjehøjde fra for hver enkelt. Du indstiller det start-Y én gang pr. kolonne, og komponenten håndterer nedstigningen
Den vandrette akse er den, du styrer manuelt. Hver kolonne sidder ved sit eget X, og efterfølgende kolonner træder til mindre X-værdier, fordi læseretningen er fra højre mod venstre. En fornuftig rytme er at vælge X for kolonnen yderst til højre og derefter trække et fast kolonnehul fra for hvert efterfølgende kald, som eksemplet gør med ColGap. Hullet er dit valg; for tæt, og tilstødende kolonner rører ved hinanden, for løst, og blokken ser tynd ud. For brødtekst på 12 til 18 punkter læses et hul, der er lidt større end skriftstørrelsen, behageligt
Glyffer, der skal ændre form
Nogle få tegn er ikke bare roterede kopier af deres vandrette selv; de skal udskiftes, når teksten bliver lodret. Den, HotPDF håndterer for dig, er det japanske forlængede lydmærke ー (U+30FC), den lange vokalbjælke, der vises i katakana-ord som コーヒー. Tegnet vandret er det en kort bindestreg på grundlinjen. Hvis du stablede den samme glyph til en kolonne, ville den ligge fladt hen over kolonnen, hvilket er forkert: på lodret japansk bliver mærket et lodret strøg, der forbinder de to tegn, det sidder imellem. HotPDF registrerer U+30FC i den lodrette sti og gengiver det som en lodret bjælke (U+007C), så det lange vokal-mærke peger den rigtige vej uden noget arbejde fra dig
Denne ene erstatning dækker det tilfælde, der ødelægger de fleste naive implementeringer, men det er værd at vide, hvor det generelle problem stikker dybere. Fuld lodret typografi roterer også latinske bogstaver og vestlig tegnsætning halvfems grader, forskyder små kana og flytter parenteser og kommaer til deres lodrette former, og en komplet implementering af dette lever i en skrifttypes OpenType lodrette funktioner i stedet for i faste regler. HotPDF kan udnytte disse funktioner, når skrifttypen bærer dem: lodrette alternativer (vert- og vrt2-GSUB-funktionerne) og lodret knibning (vkrn- og vpal-GPOS-opslag) er valgfrie, og anvendes kun langs den lodrette sti, når den aktive skrifttype faktisk definerer dem. For blandet CJK-tekst i en enkelt skrifttype med bred dækning som Arial Unicode MS er den indbyggede U+30FC-håndtering plus et jævnt linjehøjdetrin nok til at producere korrekte, læsbare kolonner; OpenType-funktionerne betyder noget, når du flytter til en skrifttype designet til fin lodret indstilling og vil have dens oprindelige kana-positionering og tegnafstand
Blanding af scripts og orienteringer på én side
Rigtige dokumenter er sjældent rene. En lodret japansk side kan bære en vandret engelsk billedtekst, et sidetal langs bunden eller en blok koreansk sat lodret ved siden af det japanske. Fordi det lodrette flag er en kontakt på skrifttypeniveau, sammensætter du disse ved at skifte mellem SetFont-kald i stedet for at styre en eventuel sidetilstand. Indstil en vandret skrifttype, skriv den løbende overskrift og sidetallet, indstil en lodret skrifttype, læg kolonnerne, indstil en vandret skrifttype igen til en sidefod. Hver region opfanger tilstanden fra det seneste SetFont, så den eneste disciplin, der kræves, er at kalde den, hver gang du ændrer retning
Én detalje, du skal planlægge for, når scripts blandes: Kinesiske, japanske og koreanske ideogrammer er tæt på at være firkantede og stables på et jævnt trin, men latinske forløb indlejret i en lodret kolonne har ikke denne ensartede fremrykning. Hvis du har brug for et par latinske ord inde i en ellers lodret tekst, skal du bevidst beslutte, om de skal roteres for at løbe ned ad kolonnen eller sættes oprejst som en kort vandret indsættelse, og placere det fragment med sit eget TextOut i stedet for at lade det ride på det lodrette trin, der er beregnet til ideogrammer. At behandle det blandede forløb som sit eget placeringsproblem holder kolonnerytmen intakt
Fra prøve til produktion
Delene er små, og de komponeres forudsigeligt. Slå det lodrette flag til i SetFont, udsend ét TextOut pr. kolonne fra et fast top-Y, og formindsk X på tværs af kald, så kolonnerne læses fra højre mod venstre. Indlejr skrifttypen, så CJK-glyfferne overlever turen til en læsers maskine, og lad komponenten håndtere U+30FC lange vokalmærket og, hvor skrifttypen understøtter dem, de lodrette OpenType-funktioner. Derfra er produktionsgørelse af layoutet for det meste aritmetik: udledning af kolonne-X-positioner fra en målt blokbredde, opdeling af lange passager i kolonner, der passer til sidehøjden, og reservation af plads til vandrette overskrifter og sidetal
For den bredere tekst- og skrifttypeoverflade, som dette bygger på, herunder de vandrette TextOut-konventioner og Unicode-skrifttyperegistrering, se det flersprogede Hello World-eksempel og TextOut-eksemplet. Den lodrette SetFont-kontakt og TextOut-kaldene, der vises her, er en del af HotPDF Component til Delphi og C++Builder