Teknisk artikkel

Vertikal japansk og kinesisk tekst i PDF med Delphi

PDFlibPas tegner japansk og kinesisk tekst nedover siden. SetVerticalWritingMode slår på vertikalt skriv, vanlige DrawText-kall løper deretter nedover, og GetVerticalWritingMode rapporterer nåværende tilstand. Før dette fantes, betydde vertikal tekst å plassere hvert tegn for hånd og håpe at avstanden så riktig ut

Vertikalt skriv er ikke horisontal tekst rotert nitti grader. Tegnene forblir opprette, forskyvningen løper nedover i stedet for på tvers, og en rekke tegn endrer form fullstendig — noe som er den delen som skiller et dokument som leses naturlig fra et en japansk leser umiddelbart gjenkjenner som maskinprodusert

Hva som endres inne i PDF-en

Tekst tegnet på denne måten går gjennom en Type0-skrift i vertikal skrivemodus som bærer skrifttypens egne vertikale mål. Det betyr noe i to retninger. En leser forskyver hvert tegn med avstanden dets designer hadde til hensikt, i stedet for med et enhetlig steg, slik at kolonnen har rytmen skriftypen ble tegnet for. Og å kopiere teksten ut returnerer de opprinnelige tegnene, fordi den vertikale løypen fortsatt er ekte tekst med en riktig tilordning snarere enn en sekvens av posisjonerte glyffer

En skrifttype som ikke bærer egne vertikale mål, forskyver én em per tegn, noe som er det en leser ville gjort med standarden. Den reserveordningen er verdt å kjenne til, fordi det er forskjellen du vil se når et dokument renderer riktig med en skikkelig CJK-skrift og ser mekanisk avstandssatt med en latinsk skrift som tilfeldigvis inneholder litt kana

var
  Lib: TPDFlib;
  H: Double;
begin
  Lib := TPDFlib.Create;
  try
    Lib.SetOrigin(1);
    Lib.AddTrueTypeFont('MS Mincho', 1);      // 1 = embed the face
    Lib.SetTextSize(12);
    Lib.SetVerticalWritingMode(1);            // ordinary DrawText now runs down
    H := Lib.GetVerticalTextHeight('MS Mincho', 12, '第三章 保守点検');
    Lib.DrawText(480, 72, '第三章 保守点検');
    Lib.SetVerticalWritingMode(0);            // back to horizontal
    Lib.DrawText(72, 72 + H, 'Chapter 3');
    Lib.SaveToFile('manual-ja.pdf');
  finally
    Lib.Free;
  end;
end;

Hvorfor ser klammer feil ut i vertikal tekst?

Fordi en klammeparentes har to former og bare én av dem hører hjem i en kolonne. Parenteser, det lange vokalteiknet og de små kana tegnes annerledes når tekst løper nedover siden — en parentes roterer for å sitte langs kolonnen snarere enn å ligge på tvers av den, og det lange vokalteiknet blir et vertikalt strek. Tegn de horisontale formene i en vertikal kolonne og alle ligger de på siden

PDFlibPas tar formene fra skrifttypens egen vertikale egenskap, slik at hver skrifttype leverer det designeren tegnet snarere enn en substitusjon gjettet fra tegnet. Den forskjellen betyr noe for korrekthet: en gjettet substitusjonstabell er riktig for de vanlige tilfellene og feil for de skrifttypene som behandler et tegn annerledes, og en skrifttype som ikke navngir noen vertikale former tegnes nøyaktig som før i stedet for å tvinges gjennom en tabell den aldri ba om

GetVerticalTextHeight måler formene som faktisk vil tegnes, slik at en kolonne hvis tegn endrer form fortsatt måles riktig. Å måle de horisontale formene og tegne de vertikale er den klassiske kilden til kolonner som overrender boksen sin med et par tegn

Tegne én løype uten å endre modusen

DrawVerticalText tegner én enkelt løype vertikalt, tar posisjon, skriftnavn, størrelse og tekst, og lar skrivemodusen være i fred. Bruk den for det vertikale unntaket inne i et horisontalt dokument — en ryggmerkeetikett, et stempel, én enkelt kolonne med navn — der å slå en global modus av og på rundt hvert kall er mer tilstand enn oppgaven krever

De horisontale og vertikale formene av én skrifttype holdes adskilt internt, slik at en side kan bære begge uten at noen forstyrrer den andre. Det er det som gjør en blandet side praktisk: en japansk bokkside med vertikal brødtekst og horisontale topptekster, eller et kinesisk sertifikat med en vertikal tittel over horisontale detaljlinjer

// One vertical run inside an otherwise horizontal page
Lib.DrawVerticalText(520, 96, 'MS Mincho', 14, '保守点検記録');
// The horizontal text around it is unaffected
Lib.DrawText(72, 96, 'Maintenance inspection record');

Å få skrifttypen riktig før noe annet

Vertikalt skriv avhenger helt av skrifttypen. En CJK-skrift med riktige vertikale mål og en vertikal egenskap produserer riktig utdata uten videre arbeid; en skrifttype uten dem produserer opprette tegn som forskyver én em av gangen og ingen formendringer i det hele tatt. Hvis vertikal tekst ser subtilt feil ut, undersøk skrifttypen før du undersøker koden

Innebygging følger de vanlige reglene og de vanlige kostnadene. En full CJK-skrifttype er stor, så delmengde-deling er ikke valgfritt for dokumenter som skal noe sted — notatene om PDF-filstørrelseoptimalisering og skriftdelmengde-deling dekker hva du kan forvente, og gjennomgangen av innebygging av manglende skrifter i en eksisterende PDF dekker reparasjonstilfellet der et vertikalt dokument ankommer uten skriftene sine

Hvor vertikal tekst fortsatt trenger en layoutbeslutning fra deg

Kolonneorden. Japansk vertikal tekst løper høyre mot venstre etter kolonne, slik at en to-kolonne-side starter ved høyre kant, og ingen skrivemodusinnstilling kan slutte det fra teksten. Det samme gjelder sideorden i et dokument som leses høyre mot venstre som helhet, og for hvor furigana, fotnoter og figur-tekster sitter

Det biblioteket garanterer er at hver løype settes riktig: riktige former, riktige forskyvninger, uttrekkbar tekst. Hvor løypene havner på siden er et layout-problem, og for dokumenter satt sammen fra data er gjennomgangen av tekstsøk og sideelement-oppramsing nyttig for å verifisere etterpå at det som landet på siden er det du hadde til hensikt

PDFlibPas er et PDF-bibliotek i ren Pascal for Delphi, C++Builder og Lazarus, og vertikalt CJK-skriv er del av tegne-API-et snarere enn et tillegg — se PDFlibPas-produktsiden for tekst- og skriftfunksjonslisten