Pošaljite arapsku rečenicu يوضح ملف PDF هذا običnom TextOut-u i stranica koja se vrati je pogrešna na dva načina odjednom. Riječi teku slijeva nadesno umjesto zdesna nalijevo, a slova sjede u svojim izoliranim oblicima umjesto da se spajaju u povezane riječi. Ništa ne javlja pogrešku. Delphi se kompajlira, datoteka se otvara, a recenzent koji čita arapski vam govori da je izlaz neupotrebljiv. Rješenje je jedan poziv, a ne zamjena biblioteke: HotPDF usmjerava zdesna nalijevo tekst kroz zasebnu metodu, RtLTextOut, koja rješava preuređivanje koje običan TextOut neće. Četiri stvari o toj metodi odlučuju je li izlaz upotrebljiv: što ona radi sa nizom, kako njezin charset (znakovni skup) argument odabire skriptu, promjena na razini dokumenta koju donosi kao nuspojavu, te rad s fontom koji mora doći prije svega
Zašto zdesna nalijevo treba vlastiti poziv
Tok sadržaja PDF-a ne pohranjuje tekst koji se može uređivati. Pohranjuje glifove na fiksnim pozicijama, što znači da što god emitira taj tok posjeduje posao odlučivanja o redu u koji idu ti glifovi. Na ekranu je operativni sustav to učinio umjesto vas: ubacite arapski u TEdit i skup teksta OS-a preuređuje ga i spaja prije nego što uopće vidite piksel. Upravo to je razlog zašto niz izgleda savršeno u vašem obrascu a lomi se u PDF-u. Desktop je odradio posao tiho, i u trenutku kada ispisujete svoj vlastiti tok, posao je opet natrag na vašoj strani
TextOut vas shvaća doslovno. Crta kodne točke u onom redoslijedu u kojem ih proslijedite, slijeva nadesno, što je točno za latinicu, ćirilicu, i CJK, a pogrešno za arapski i hebrejski. RtLTextOut je poziv koji prvo preuređuje liniju u vizualni zdesna nalijevo redoslijed, a zatim crta. HotPDF namjerno drži dvije metode odvojenima radije nego da nagađa smjer po znakovima, tako da je izbor koju odabrati onaj izbor o tome kakvo ponašanje dobivate. Dublja mehanika bidirekcionalnog preuređivanja i arapskog kontekstualnog spajanja su svoja vlastita tema, obrađena u članku o arapskom i RTL oblikovanju teksta uz HotPDF; ovdje je poenta suženija i praktičnija. Koristite RtLTextOut za nizove zdesna nalijevo, koristite TextOut za sve ostalo, i nikada jedno ne preusmjeravajte kroz to drugo

procedure RtLTextOut(X, Y: Single; angle: Extended;
Text: WideString); overload;
procedure RtLTextOut(X, Y: Single; angle: Extended;
Text: PWORD; TextLength: Integer); overload;
Argument skupa znakova (charset) odlučuje o pismu (skripti)
Ono što govori RtLTextOut-u postavlja li arapski ili hebrejski nije metoda, već sam font. SetFont uzima Windows skup znakova kao svoj četvrti argument, a ta vrijednost sa sobom nosi pravila pisma u zdesna nalijevo poziv: 178 odabire arapski, a 177 bira hebrejski. Postavite skup znakova, zatim crtajte, i obje donje linije bi trebale biti s ispravnim redoslijedom čitanja bez ikakve daljnje konfiguracije
Dva detalja oko tih koordinata je lako previdjeti. Pozicija koju proslijedite i dalje je početak tog niza unutar vlastitog koordinatnog sustava stranice, mjerenog od donjeg lijevog kuta uz Y rastući prema gore, na istom izvorištu koje svaki TextOut koristi; RtLTextOut mijenja redoslijed glifova, a ne odakle stranica mjeri. A kao i sa svakim pozivom na iscrtavanje, SetFont mora doći prvi i mora biti ponovljen nakon svakog AddPage-a, zato što trenutni font ne preživi prekid stranice. Zaboravite ponavljanje, a ta druga stranica se vraća na bilo koji font koji je bio aktivan, što za arapski obično znači prazne okvire
// Arabic: charset 178 tells RtLTextOut to apply Arabic rules
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 700, 0, 'يوضح ملف PDF هذا');
// Hebrew: charset 177 switches the rules to Hebrew
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 177);
Pdf.CurrentPage.RtLTextOut(400, 660, 0, 'קובץ PDF זה');
Ne okreće tekst koji ste već sami okrenuli
Jedna pogreška koja guta najviše vremena za otklanjanje grešaka ovdje je hranjenje RtLTextOut-a nizom koji ste već ručno preokrenuli. Ljudi dolaze do ove metode nakon prvog pokušaja s običnim TextOut-om koji izađe unatrag, a uobičajena privremena mjera je obrnuti znakove u kodu prije crtanja. RtLTextOut preokreće interno sam od sebe, tako da unaprijed preokrenuti niz bude preokrenut drugi put i sleti natrag tamo odakle je krenuo. Proslijedite tekst u logičnom redoslijedu, redoslijedu u kojem biste ga otipkali i pročitali naglas, i dopustite pozivu da napravi preuređivanje
Zamka je gadnija od običnog preokretanja zato što dvostruko-preokrenut niz može izgledati ispravno za jednu posve arapsku testnu frazu i onda se slomiti onog trenutka kada linija ponese latiničnu riječ ili broj. Unutar linije zdesna nalijevo ti ugrađeni nizovi bi se trebali čitati slijeva nadesno, a ručno preokretanje uništava to gniježđenje dok čisti arapski slučaj to preživi. Stoga taj bug otplovi kroz vaš prvi "smoke test" i ispliva kasnije na nekoj pravoj fakturi s brojem računa u njoj. Uklonite svaki ručni preokret onog trenutka kada pređete na RtLTextOut
Nuspojava smjera (Direction) vrijedna znanja
Pozivanje RtLTextOut mijenja više od linije koju crtate. Ono također okreće dokumentovu preferenciju smjera čitanja u zdesna nalijevo, istu stvar koju biste inače postavili sami kroz svojstvo Direction. Taj setter dodaje vpDirection u dokumentove ViewerPreferences, što govori pregledniku kako da rasporedi dvije-gore prijelome i s koje strane počinje raspored suočenih stranica. Kada je čitav dokument arapski ili hebrejski ovo je točno ono što želite, i dobijete to besplatno
To vrijedi znati upravo zato što je nevidljivo na jednoj stranici. Ako je dokument većinom slijeva nadesno s jednim zdesna nalijevo blokom, prvi RtLTextOut poziv će i dalje nagnuti cijelu preferenciju datoteke, a ništa u vašem probnom otisku od jedne stranice to neće pokazati. Simptom se pojavljuje tjednima kasnije kada netko ispisuje dvostranu knjižicu a prijelomi izađu zrcaljeni. Ako to nije ono što želite, postavite Direction natrag eksplicitno nakon niza zdesna nalijevo:
Za dokument koji se istinski čita zdesna nalijevo, ostavite ga na miru. Poenta je znati da poziv ima efekt na razini cijelog dokumenta kako se iznenađenje s knjižicom nikada ne bi dogodilo
// RtLTextOut already set the document direction to RightToLeft;
// restore left-to-right if the document is predominantly LTR
Pdf.Direction := LeftToRight;
Registrirajte font koji isporučujete, a ne onaj za koji se nadate da je instaliran
Ništa od preuređivanja nije bitno ako font nema glifova za crtanje. Klasični kvar je izvještaj koji se besprijekorno renderira na programerovom stroju, gdje se Arial Unicode MS zatekne prisutnim, i izađe kao niz praznih okvira na korisnikovom serveru gdje je Windows tiho zamijenio font bez arapske pokrivenosti uopće. Lijek je da prestanete vjerovati instaliranim sistemskim fontovima i registrirate onaj koji isporučujete uz aplikaciju
Dva ograničenja dolaze skupa sa registracijom. Font koji se unese kroz RegisterUnicodeTTF biva ugrađen, i HotPDF-ovo rukovanje ugrađenim Unicode-om zahtijeva da dokument bude na PDF 1.5 ili novijoj verziji; to predstavlja problem samo ako nešto nizvodno ustraje na PDF-u 1.4, ali kada to bude greška je tiha. Drugo ograničenje je više pravno nego tehničko: TrueType datoteke nose bitove dopuštenja za ugradnju, i font koji izgleda dobro na ekranu može biti licenciran na način koji zabranjuje njegovo isporučivanje u korisničkim dokumentima. Potvrdite licencu prije ugradnje, a ne nakon prigovora
// Ship a known Arabic font and register it before drawing
Pdf.RegisterUnicodeTTF('C:\Fonts\NotoSansArabic.ttf');
Pdf.CurrentPage.SetFont('NotoSansArabic', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 700, 0, 'يوضح ملف PDF هذا');
Potpuni primjer konzole
Sastavljajući ove komade, ovdje je samostalni program koji piše jednu stranicu sa arapskom linijom, hebrejskom linijom, i mješovitom linijom koja nosi latinski naziv proizvoda. Svaki blok postavlja svoj znakovni skup, a zatim crta u logičnom redoslijedu
Pokrenite ga i otvorite rezultat. Arapske i hebrejske linije čitaju se zdesna nalijevo, slova se spajaju gdje ih skripta (pismo) spaja, a u zadnjoj liniji token HotPDF sjedi slijeva nadesno unutar arapskog niza, što je prema specifikaciji ispravan rezultat iako iznenađuje svakoga tko prvi put vidi dvosmjerni raspored. Tu posljednju točku vrijedi zapisati u vaše kriterije prihvaćanja prije nego izvorni čitatelj pregleda izlaz, jer ugrađeni niz koji se čita na "pogrešan" način u odnosu na okolno pismo je jedina stvar koja se najčešće prijavljuje kao bug kada to zapravo nije
program RtLTextOutDemo;
{$APPTYPE CONSOLE}
uses
HPDFDoc; // HotPDF main unit
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'RtLTextOut.pdf';
Pdf.BeginDoc;
// A Latin heading goes through the ordinary TextOut path
Pdf.CurrentPage.SetFont('Arial', [fsBold], 16);
Pdf.CurrentPage.TextOut(40, 780, 0, 'Right-to-left text with HotPDF');
// Arabic: charset 178, logical order, RtLTextOut does the reordering
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 720, 0,
'يوضح ملف PDF هذا كيفية التعامل مع النص العربي.');
// Hebrew: charset 177
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 177);
Pdf.CurrentPage.RtLTextOut(400, 680, 0,
'קובץ PDF זה מדגים טקסט עברי הזורם מימין לשמאל.');
// Mixed line: the embedded Latin word still reads left to right
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.
Provjera izlaza
Stranica koja izgleda ispravno nije ista kao i stranica koja je ispravna, pa to provjerite na način na koji bi to napravio neki nizvodni sustav. Kopirajte tekst iz preglednika i usporedite kodne točke s vašim izvornim nizom; ispravan vizualni redoslijed uz ispremiješan logički redoslijed stvarni je način kvara. Pokrenite preglednikovu pretragu unutar dokumenta za riječ koju možete vidjeti na stranici. Zatim otvorite datoteku na računalu koje nema vaše razvojne fontove, onom koje će najvjerojatnije otkriti tihu zamjenu. Ništa od toga ne zamjenjuje izvornog govornika koji čita jedan pravi dokument, što hvata probleme koje nijedan sintetički probni niz neće, stoga stavite taj pregled na kalendar prije isporuke samog formata
RtLTextOut obrađuje bidirekcionalno preuređivanje i arapsko kontekstualno spajanje, što pokriva veliku većinu izrada dokumenata zdesna nalijevo. Tamo gdje se zaustavlja, skripte (pisma) kojima je potrebno više od preuređivanja i spajanja kao što su indijske obitelji, te opcionalne OpenType značajke koje prolaze kroz zamjenu jednog glifa, mapirane su zajedno s detaljima pokrivenosti glifova i oblikovanja u popratnom članku o arapskom i RTL oblikovanju teksta uz HotPDF
Pozivi RtLTextOut, SetFont, i RegisterUnicodeTTF prikazani ovdje dio su komponente HotPDF Component za Delphi i C++Builder