Articol tehnic

Text japonez și chinezesc vertical în PDF cu Delphi

PDFlibPas desenează text japonez și chinezesc în josul paginii. SetVerticalWritingMode activează scrierea verticală, apoi apelurile obișnuite DrawText rulează în jos, iar GetVerticalWritingMode raportează starea curentă. Înainte de asta, așezarea textului pe verticală însemna plasarea fiecărui caracter manual și sperarea că spațierea arată bine

Scrierea verticală nu este text orizontal rotit nouăzeci de grade. Caracterele rămân verticale, avansul rulează în jos în loc de-a curmezișul, iar o serie de caractere își schimbă complet forma — partea care separă un document care se citește natural de unul pe care un cititor japonez îl recunoaște imediat ca produs de mașină

Ce se schimbă în interiorul PDF-ului

Textul desenat astfel trece printr-un font Type0 în modul de scriere verticală purtând metricile verticale proprii ale fontului. Asta contează în două direcții. Un cititor avansează fiecare caracter cu distanța pe care a intenționat-o designerul său, nu cu un pas uniform, astfel încât coloana are ritmul pentru care a fost desenat tipul de caractere. Și copierea textului returnează caracterele originale, deoarece secvența verticală este încă text real cu o mapare corespunzătoare, nu o secvență de glife poziționate

Un font care nu poartă propriile metrici verticale avansează un em pe caracter, exact ce ar face un cititor cu valoarea implicită. Această rezervă merită cunoscută deoarece este diferența pe care o veți vedea când un document randează corect cu un font CJK propriu și arată mecanic spațiat cu un font latin care se întâmplă să conțină niște 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;

De ce arată parantezele greșit în text vertical?

Pentru că o paranteză are două forme și doar una dintre ele aparține într-o coloană. Parantezele, marca de vocală lungă și kana mici sunt desenate diferit când textul rulează în josul paginii — o paranteză se rotește să stea de-a lungul coloanei în loc să zacă peste ea, iar marca de vocală lungă devine o tușă verticală. Desenați formele orizontale într-o coloană verticală și fiecare dintre ele zace pe o parte

PDFlibPas ia formele din caracteristica verticală a propriului font, astfel încât fiecare font livrează ceea ce a desenat designerul său, nu o substituție ghicită din caracter. Această distincție contează pentru corectitudine: un tabel de substituții ghicit este corect pentru cazurile comune și greșit pentru fonturile care tratează un caracter diferit, iar un font care nu numește nicio formă verticală este desenat exact ca înainte, în loc să fie forțat printr-un tabel pe care nu l-a cerut niciodată

GetVerticalTextHeight măsoară formele care vor fi de fapt desenate, astfel încât o coloană ale cărei caractere își schimbă forma este încă măsurată corect. Măsurarea formelor orizontale și desenarea celor verticale este sursa clasică a coloanelor care depășesc căsuța lor cu câteva caractere

Desenarea unei singure secvențe fără schimbarea modului

DrawVerticalText desenează o singură secvență vertical, luând poziția, numele fontului, dimensiunea și textul, și lasă modul de scriere în pace. Folosiți-l pentru excepția verticală din interiorul unui document orizontal — o etichetă de cotor, o ștampilă, o singură coloană de nume — unde comutarea unui mod global în jurul fiecărui apel este mai multă stare decât merită sarcina

Formele orizontale și verticale ale unui font sunt ținute separat intern, astfel încât o pagină poate purta ambele fără ca una să o deranjeze pe cealaltă. Asta face practică o pagină mixtă: o pagină de carte japoneză cu text-corp vertical și anteturi curente orizontale, sau un certificat chinezesc cu un titlu vertical peste linii de detaliu orizontale

// 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');

Alegerea fontului corect înainte de orice altceva

Scrierea verticală depinde în întregime de font. Un font CJK cu metrici verticale proprii și o caracteristică verticală produce ieșire corectă fără altă muncă; un font fără ele produce caractere verticale care avansează un em pe rând și nicio schimbare de formă. Dacă textul vertical arată subtil greșit, examinați fontul înainte de a examina codul

Încorporarea urmează regulile și costurile obișnuite. Un font CJK complet este mare, astfel încât submulțimea nu este opțională pentru documentele care pleacă oriunde — notele despre optimizarea dimensiunii fișierului PDF și submulțimea de font acoperă ce să expectați, iar prezentarea detaliată despre încorporarea fonturilor lipsă într-un PDF existent acoperă cazul de reparație când un document vertical sosește fără fonturile sale

Unde are textul vertical încă nevoie de o decizie de aspect de la dumneavoastră

Ordinea coloanelor. Textul vertical japonez rulează de la dreapta la stânga pe coloană, astfel încât o pagină cu două coloane începe de la marginea dreaptă, iar nicio setare a modului de scriere nu poate deduce asta din text. Același lucru se aplică ordinii paginilor într-un document care se citește de la dreapta la stânga ca întreg, și locului unde stau furigana, notele de subsol și legendele figurilor

Ceea ce garantează biblioteca este că fiecare secvență este așezată corect: forme corecte, avansuri corecte, text extraibil. Unde merg secvențele pe pagină este o problemă de aspect, iar pentru documentele asamblate din date prezentarea detaliată despre căutarea de text și enumerarea elementelor de pagină este utilă pentru verificarea ulterioară că ceea ce a ajuns pe pagină este ceea ce ați intenționat

PDFlibPas este o bibliotecă PDF nativă în Pascal pentru Delphi, C++Builder și Lazarus, iar scrierea CJK verticală face parte din API-ul de desen mai degrabă decât un modul suplimentar — vedeți pagina produsului PDFlibPas pentru lista de funcții text și font