Pošljite arabski stavek يوضح ملف PDF هذا navadnemu TextOut in stran, ki se vrne, je napačna na dva načina hkrati. Besede tečejo od leve proti desni namesto od desne proti levi, črke pa stojijo narazen v svojih osamljenih oblikah, namesto da bi se povezale v sklenjene besede. Nič ne javi napake. Delphi se prevede, datoteka se odpre, pregledovalec, ki bere arabsko, pa vam pove, da je izhod neuporaben. Popravek je en klic in ne zamenjava knjižnice: HotPDF besedilo od desne proti levi napelje skozi ločeno metodo, RtLTextOut, ki poskrbi za prerazporeditev, kakršne navadni TextOut ne opravi. Ta stran je delovna referenca za to metodo: podpis in njegovi parametri, argument nabora znakov, ki izbere pisavni sistem, stranski učinek na ravni dokumenta, nastavitev pisave, ki mora priti prva, in odpovedi, ki resnično pridejo do podpore, vsaka s svojim popravkom
Podpis in parametri
procedure RtLTextOut(X, Y: Single; angle: Extended;
Text: WideString); overload;
procedure RtLTextOut(X, Y: Single; angle: Extended;
Text: PWORD; TextLength: Integer); overload;
X in Y zasidrata niz v lastnem koordinatnem sistemu strani, merjeno od spodnjega levega kota z Y, ki raste navzgor, torej z istim izhodiščem, kot ga uporablja vsak klic TextOut; RtLTextOut spremeni vrstni red znakov in ne tega, od kod stran meri. angle zasuka osnovnico natanko tako kot v TextOut, zato 0 nariše vodoravno vrstico. Text je niz v logičnem vrstnem redu, torej v vrstnem redu, kakor bi ga natipkali, druga preobložitev pa vzame iste podatke UTF-16 kot goli medpomnilnik PWORD z izrecnim številom kodnih enot, kar je oblika, ki jo uporabite, kadar besedilo pride iz API-ja in ne iz niza v Delphiju. V starejših različicah Delphija, ki so nastale pred razreševanjem preobložitev za te tipe, je oblika z nizom razkrita pod imenom RtLTextOutStr z identičnim seznamom parametrov
Delitev dela med obema izpisnima klicema je stroga. TextOut nariše kodne točke v vrstnem redu, v katerem jih podate, kar je pravilno za latinico, cirilico in CJK ter napačno za arabsko in hebrejsko pisavo. RtLTextOut vsako vrstico najprej prerazporedi v vidni vrstni red od desne proti levi in šele nato riše, pri čemer vgrajene latinične besede in števke znotraj vrstice ohrani berljive od leve proti desni. HotPDF metodi namerno drži ločeni, namesto da bi smer ugibal iz znakov, zato je izbira, katero poklicati, izbira, kakšno vedenje pisavnega sistema dobite; RtLTextOut uporabite za nize od desne proti levi, TextOut za vse drugo, enega pa nikoli ne napeljujte skozi drugega. Zakaj prerazporejanje sploh obstaja, kaj Unicodeov dvosmerni algoritem in arabsko kontekstno spajanje v resnici počneta ter kje se oblikovanje v HotPDF ustavi, je tema spremnega članka o oblikovanju arabskega in RTL besedila s HotPDF; vse spodaj je praktična nastavitev

Argument nabora znakov odloči o pisavnem sistemu
Kaj RtLTextOut pove, ali postavlja arabsko ali hebrejsko besedilo, ni metoda, ampak pisava. SetFont kot četrti argument vzame nabor znakov Windows, ta vrednost pa pravila pisavnega sistema prenese v klic od desne proti levi: 178 izbere arabsko, 177 izbere hebrejsko. Nastavite nabor znakov, nato rišite, in spodnji vrstici prideta ven v pravilnem bralnem vrstnem redu brez kakršne koli nadaljnje nastavitve
// Arabsko: nabor znakov 178 pove RtLTextOut, naj uporabi arabska pravila
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 700, 0, 'يوضح ملف PDF هذا');
// Hebrejsko: nabor znakov 177 pravila preklopi na hebrejska
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 177);
Pdf.CurrentPage.RtLTextOut(400, 660, 0, 'קובץ PDF זה');
Eno podrobnost glede zaporedja je zlahka spregledati: SetFont mora priti prvi in mora biti ponovljen po vsakem AddPage, saj trenutna pisava, skupaj z naborom znakov, preloma strani ne preživi. Pozabite na ponovitev in druga stran se zateče k tisti pisavi, ki je bila dejavna, kar za arabsko besedilo običajno pomeni prazne kvadratke
Ne obrne besedila, ki ste ga že obrnili
Ena sama napaka tu požre največ časa za razhroščevanje: podati RtLTextOut niz, ki ste ga ročno že obrnili. Ljudje do te metode pridejo, potem ko je prvi poskus z navadnim TextOut prišel ven obrnjeno, pogosta zasilna rešitev pa je, da znake pred risanjem obrnejo v kodi. RtLTextOut obrača interno sam, zato se vnaprej obrnjen niz obrne še drugič in pristane natanko tam, kjer je začel. Besedilo podajte v logičnem vrstnem redu, torej v takem, kot bi ga natipkali in prebrali na glas, prerazporejanje pa prepustite klicu
Past je hujša od navadnega obrata, ker je dvojno obrnjen niz lahko videti pravilen pri eni sami povsem arabski preizkusni frazi in se sesuje v trenutku, ko vrstica nosi latinično besedo ali število. Znotraj vrstice od desne proti levi naj bi se ti vgrajeni nizi brali od leve proti desni, ročno obračanje pa to gnezdenje uniči, medtem ko čisto arabski primer to po naključju preživi. Napaka torej gladko prepluje vaš prvi dimni test in se pojavi pozneje na resničnem računu s številko računa v njem. Vsako ročno obračanje odstranite v trenutku, ko preidete na RtLTextOut
Stranski učinek na Direction, ki ga je vredno poznati
Klic RtLTextOut spremeni več kot le vrstico, ki jo rišete. Bralno smer dokumenta prevesi tudi na od desne proti levi, torej na isto, kar bi sicer sami nastavili prek lastnosti Direction. Ta nastavljalnik doda vpDirection v ViewerPreferences dokumenta, kar pregledovalniku pove, kako naj razporedi dvostranske razprostrtice in s katere strani se začne postavitev z nasproti ležečimi stranmi. Kadar je celoten dokument arabski ali hebrejski, je to natanko to, kar želite, in dobite zastonj
Vredno je vedeti zanj prav zato, ker je na eni sami strani neviden. Če je dokument večinoma od leve proti desni z enim samim blokom od desne proti levi, bo prvi klic RtLTextOut vseeno prevesil nastavitev celotne datoteke, in nič v vašem enostranskem poskusu tega ne bo pokazalo. Simptom se pojavi tedne pozneje, ko nekdo natisne obojestransko knjižico in razprostrtice pridejo ven zrcaljene. Če tega ne želite, po nizu od desne proti levi Direction izrecno nastavite nazaj:
// RtLTextOut je smer dokumenta že nastavil na RightToLeft;
// obnovite od leve proti desni, če je dokument pretežno LTR
Pdf.Direction := LeftToRight;
Pri dokumentu, ki se resnično bere od desne proti levi, tega ne spreminjajte. Bistvo je vedeti, da ima klic učinek na celoten dokument, tako da presenečenja s knjižico nikoli ne bo
Registrirajte pisavo, ki jo odpremite, ne tiste, za katero upate, da je nameščena
Nobeno prerazporejanje ni pomembno, če pisava nima znakov za risanje. Klasična odpoved je poročilo, ki se na razvijalčevem stroju, kjer je Arial Unicode MS pač prisoten, upodobi brezhibno, na strankinem strežniku pa pride ven kot vrste praznih kvadratkov, ker je Windows tiho zamenjal pisavo s takšno brez vsakršne arabske pokritosti. Zdravilo je, da nehate zaupati nameščenim sistemskim pisavam in registrirate tisto, ki jo odpremite skupaj z aplikacijo
// Odpremite znano arabsko pisavo in jo registrirajte pred risanjem
Pdf.RegisterUnicodeTTF('C:\Fonts\NotoSansArabic.ttf');
Pdf.CurrentPage.SetFont('NotoSansArabic', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 700, 0, 'يوضح ملف PDF هذا');
Z registracijo prideta dve meji. Pisava, vnesena prek RegisterUnicodeTTF, se vdela, obravnava vdelanega Unicode v HotPDF pa potrebuje dokument v PDF 1.5 ali novejši; to ugrizne le, kadar kaj nižje po toku vztraja pri PDF 1.4, a takrat je odpoved tiha. Druga meja je pravna in ne tehnična: datoteke TrueType nosijo bite z dovoljenjem za vdelavo, pisava, ki je na zaslonu videti povsem v redu, pa je lahko licencirana tako, da njeno odpremo znotraj strankinih dokumentov prepoveduje. Licenco potrdite pred vdelavo in ne po pritožbi
Celovit konzolni primer
Ko sestavimo koščke skupaj, je pred nami samostojen program, ki zapiše eno stran z arabsko vrstico, hebrejsko vrstico in mešano vrstico z latiničnim imenom izdelka. Vsak blok nastavi svoj nabor znakov, nato pa riše v logičnem vrstnem redu
program RtLTextOutDemo;
{$APPTYPE CONSOLE}
uses
HPDFDoc; // glavna enota HotPDF
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'RtLTextOut.pdf';
Pdf.BeginDoc;
// Latinični naslov gre po običajni poti TextOut
Pdf.CurrentPage.SetFont('Arial', [fsBold], 16);
Pdf.CurrentPage.TextOut(40, 780, 0, 'Right-to-left text with HotPDF');
// Arabsko: nabor znakov 178, logični vrstni red, prerazporeja RtLTextOut
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 720, 0,
'يوضح ملف PDF هذا كيفية التعامل مع النص العربي.');
// Hebrejsko: nabor znakov 177
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 177);
Pdf.CurrentPage.RtLTextOut(400, 680, 0,
'קובץ PDF זה מדגים טקסט עברי הזורם מימין לשמאל.');
// Mešana vrstica: vgrajena latinična beseda se še vedno bere od leve proti desni
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 640, 0,
'مرحبا بالعالم! تم إنشاؤه بواسطة HotPDF');
Pdf.EndDoc;
Writeln('Wrote RtLTextOut.pdf');
finally
Pdf.Free;
end;
end.
Poženite ga in odprite izid. Arabska in hebrejska vrstica se bereta od desne proti levi, črke se povežejo tam, kjer jih pisavni sistem povezuje, v zadnji vrstici pa žeton HotPDF sedi od leve proti desni znotraj arabskega niza. To gnezdenje je pravilen dvosmerni izid in ne napaka, čeprav ga pregledovalci ob prvem srečanju redno prijavijo kot napako; zgoraj povezani članek o oblikovanju pojasnjuje, zakaj pravila Unicode to terjajo in kako ubesediti merila sprejemljivosti, da do prijave nikoli ne pride
Pogoste napake in njihovi popravki
Vsaka spodnja odpoved se je pojavila v resnični podporni niti in vsaka se vrača k enemu od zgornjih razdelkov
- Izhod se bere obrnjeno ali se v mešanih vrsticah premeša — niz je bil pred klicem ročno obrnjen, običajno kot ostanek zasilne rešitve iz poskusa s
TextOut. Izbrišite vsako ročno obračanje in podajte logični vrstni red;RtLTextOutobrača interno - Črke se natisnejo nepovezano v osamljenih oblikah — besedilo je šlo skozi navadni
TextOutali pa je bilSetFontpoklican brez nabora znakov za desno-levo pisavo. Rišite zRtLTextOutin kot četrti argumentSetFontpodajte 178 za arabsko ali 177 za hebrejsko - Prazni kvadratki na strankinem stroju — Windows je zamenjal pisavo s takšno brez arabske ali hebrejske pokritosti. Nehajte navajati nameščene pisave; registrirajte pisavo, ki jo odpremite, prek
RegisterUnicodeTTFin jo po tem imenu nastavite sSetFont - Druga stran se upodobi v napačni pisavi — trenutna pisava ne preživi
AddPage. KlicSetFont, skupaj z naborom znakov, ponovite po vsakem prelomu strani - Obojestranske razprostrtice se pri pretežno LTR dokumentu natisnejo zrcaljeno — prvi klic
RtLTextOutje kot stranski učinek prevesilDirectiondokumenta. Po nizu od desne proti levi nastavitePdf.Direction := LeftToRight - Vdelano besedilo Unicode se nižje po toku tiho poslabša — nekaj v cevovodu vsiljuje PDF 1.4, obravnava vdelanega Unicode v HotPDF pa potrebuje 1.5 ali novejšo. Dvignite različico dokumenta ali odstranite omejitev nižje po toku
Preden zapis odide v svet, preverjajte onkraj ocene na oko: besedilo skopirajte nazaj iz pregledovalnika, poženite iskanje znotraj dokumenta, datoteko odprite na stroju brez vaših razvojnih pisav in en pristen dokument položite pred domačega bralca. Celoten seznam preverjanj, zemljevid pokritosti po pisavnih sistemih in nabor preizkusnih nizov, ki jih je vredno zgraditi, živijo v spremnem članku o oblikovanju arabskega in RTL besedila s HotPDF
Klici RtLTextOut, SetFont in RegisterUnicodeTTF, prikazani tukaj, so del komponente HotPDF Delphi za Delphi in C++Builder